[Pkg-voip-commits] r3905 - in zaptel/trunk: cwain debian qozap zaphfc ztgsm

paravoid at alioth.debian.org paravoid at alioth.debian.org
Sun Aug 5 11:43:22 UTC 2007


Author: paravoid
Date: 2007-08-05 11:43:22 +0000 (Sun, 05 Aug 2007)
New Revision: 3905

Added:
   zaptel/trunk/cwain/zaptel.conf.hdlcnet
   zaptel/trunk/cwain/zaptel.conf.hdlcnet.doubleE1
   zaptel/trunk/qozap/zapata.conf.duoBRI
   zaptel/trunk/qozap/zaptel.conf.duoBRI
Modified:
   zaptel/trunk/debian/changelog
   zaptel/trunk/qozap/qozap.c
   zaptel/trunk/qozap/zaptel.conf
   zaptel/trunk/qozap/zaptel.conf.octoBRI
   zaptel/trunk/zaphfc/zaphfc.c
   zaptel/trunk/ztgsm/ztgsm.c
   zaptel/trunk/ztgsm/ztgsm.h
Log:
Update zaphfc, qozap, cwain and ztgsm from -test4

Added: zaptel/trunk/cwain/zaptel.conf.hdlcnet
===================================================================
--- zaptel/trunk/cwain/zaptel.conf.hdlcnet	                        (rev 0)
+++ zaptel/trunk/cwain/zaptel.conf.hdlcnet	2007-08-05 11:43:22 UTC (rev 3905)
@@ -0,0 +1,8 @@
+loadzone=nl
+defaultzone=nl
+span=1,1,3,ccs,hdb3,crc4
+
+; hdlc0
+hdlcnet=1
+
+

Added: zaptel/trunk/cwain/zaptel.conf.hdlcnet.doubleE1
===================================================================
--- zaptel/trunk/cwain/zaptel.conf.hdlcnet.doubleE1	                        (rev 0)
+++ zaptel/trunk/cwain/zaptel.conf.hdlcnet.doubleE1	2007-08-05 11:43:22 UTC (rev 3905)
@@ -0,0 +1,10 @@
+loadzone=nl
+defaultzone=nl
+span=1,1,3,ccs,hdb3,crc4
+span=2,2,3,ccs,hdb3,crc4
+
+; hdlc0
+hdlcnet = 1
+
+; hdlc 1
+hdlcnet = 2
\ No newline at end of file

Modified: zaptel/trunk/debian/changelog
===================================================================
--- zaptel/trunk/debian/changelog	2007-08-05 11:21:06 UTC (rev 3904)
+++ zaptel/trunk/debian/changelog	2007-08-05 11:43:22 UTC (rev 3905)
@@ -11,9 +11,11 @@
     locations of zaptel.h and tonezone.h .
 
   [ Faidon Liambotis ]
-  * Include zaptel.patch from bristuff 0.4.0-test4 (bristuff.dpatch).
+  * bristuff 0.4.0-test4 
+    - Add zaptel.patch as debian/patches/bristuff.dpatch.
+    - Update zaphfc, qozap, cwain and ztgsm.
 
- -- Faidon Liambotis <paravoid at debian.org>  Sun, 05 Aug 2007 13:39:23 +0300
+ -- Faidon Liambotis <paravoid at debian.org>  Sun, 05 Aug 2007 14:41:53 +0300
 
 zaptel (1:1.4.4~dfsg-1) unstable; urgency=low
 

Modified: zaptel/trunk/qozap/qozap.c
===================================================================
--- zaptel/trunk/qozap/qozap.c	2007-08-05 11:21:06 UTC (rev 3904)
+++ zaptel/trunk/qozap/qozap.c	2007-08-05 11:43:22 UTC (rev 3905)
@@ -2,7 +2,7 @@
  * qozap.c - Zaptel driver for the quadBRI PCI ISDN card
  * and the octoBRI PCI ISDN card!
  *
- * Copyright (C) 2003, 2004, 2005, 2006 Junghanns.NET GmbH
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007 Junghanns.NET GmbH
  *
  * Klaus-Peter Junghanns <kpj at junghanns.net>
  *
@@ -29,12 +29,13 @@
 static int pcmslave=0;
 static int bloop=0;
 static int debug=0;
-static int dacs=1;
+static int dacs=1; /* 0 = no dacs, 1 = oncard dacs */
 static struct qoz_card *qoz_dev_list = NULL;
 static int qoz_dev_count = 0;
 static int totalBRIs = 0;
 static struct pci_dev *multi_qoz = NULL;
 static spinlock_t registerlock = SPIN_LOCK_UNLOCKED;
+static int sort=1;
 
 static int ztqoz_shutdown(struct zt_span *span);
 
@@ -107,83 +108,178 @@
 
 void qoz_doLEDs(struct qoz_card *qoztmp) {
     unsigned char leds = 0x0;
+    unsigned long ledw;
     unsigned long flags;
     spin_lock_irqsave(&qoztmp->lock,flags);
 
     if ((qoztmp->type == 0xb520) && (qoztmp->stports == 4)){
-//	if ((qoztmp->ticks > 0) && (qoztmp->ticks <= 300)) {
 	    qoz_outb(qoztmp,qoz_R_GPIO_SEL,0x20 | 0x10);
     	    qoz_outb(qoztmp,qoz_R_GPIO_EN1,0xf);
 	    qoz_outb(qoztmp,qoz_R_GPIO_OUT1,(qoztmp->leds[0] | (qoztmp->leds[1] << 1) | (qoztmp->leds[2] << 2) | (qoztmp->leds[3] << 3)));
-/*	}
-	if ((qoztmp->ticks > 300) && (qoztmp->ticks <= 600)) {
-    	    qoz_outb(qoztmp,qoz_R_GPIO_EN1,0x0);
-	} */
-    } else if ((qoztmp->type == 0xb550) && (qoztmp->stports == 4)){
+    } else if (((qoztmp->type == 0xb550)  || (qoztmp->type == 0xb556)) && (qoztmp->stports == 4)){
 	    qoz_outb(qoztmp,qoz_R_GPIO_SEL,0x80 | 0x40 | 0x20 | 0x10);
     	    qoz_outb(qoztmp,qoz_R_GPIO_EN1,0xff);
-	    if (qoztmp->leds[0] == 0) {
+	    leds = 0x10;
+	    if (qoztmp->leds[0] == 1) {
+		leds |= 0x04;
+	    }
+	    if (qoztmp->leds[1] == 1) {
+		leds |= 0x20;
+	    }
+	    if (qoztmp->leds[2] == 1) {
 		leds |= 0x80;
-	    } else {
+	    }
+	    if (qoztmp->leds[3] == 1) {
 		leds |= 0x40;
 	    }
-	    if (qoztmp->leds[1] == 0) {
-		leds |= 0x10;
-	    } else {
-		leds |= 0x20;
+
+    /*
+	     03
+	     12
+	0x80 rr
+	     rg
+	0x40 rg
+	     rr
+	0x20 rr
+	     gr
+	0x04 gr
+	     rr
+    */
+	    qoz_outb(qoztmp,qoz_R_GPIO_OUT1, leds);
+
+    } else if ((qoztmp->type == 0xb556) && (qoztmp->stports == 2)){
+	    qoz_outb(qoztmp,qoz_R_GPIO_SEL,0x80 | 0x40 | 0x20 | 0x10);
+    	    qoz_outb(qoztmp,qoz_R_GPIO_EN1,0xff);
+	    leds = 0x0;
+	    if (qoztmp->leds[0] == 1) {
+		leds |= 0x04;
 	    }
-	    if (qoztmp->leds[2] == 0) {
-		leds |= 0x04;
-	    } else {
+	    if (qoztmp->leds[1] == 1) {
 		leds |= 0x08;
 	    }
-	    if (qoztmp->leds[3] == 0) {
-		leds |= 0x02;
-	    } else {
-		leds |= 0x01;
+	    qoz_outb(qoztmp,qoz_R_GPIO_OUT1, leds);
+
+    } else if (qoztmp->type == 0xb558) {
+	    qoz_outb(qoztmp,qoz_R_GPIO_SEL,0x80 | 0x40 | 0x20);
+    	    qoz_outb(qoztmp,qoz_R_GPIO_EN1,0x80 | 0x40 | 0x20 | 0x4);
+	    if (qoztmp->leds[0] == 1) {
+		leds |= 0x04;
 	    }
-    /* 	0x80 st1g
-	0x40 st1r
-	0x20 st2r
-	0x10 st2g	
-	0x08 st3r
-	0x04 st3g
-	0x02 st4g
-	0x01 st4r
-    */
+	    if (qoztmp->leds[1] == 1) {
+		leds |= 0x20;
+	    }
+	    if (qoztmp->leds[2] == 1) {
+		leds |= 0x40;
+	    }
+	    if (qoztmp->leds[3] == 1) {
+		leds |= 0x80;
+	    }
+	    
 	    qoz_outb(qoztmp,qoz_R_GPIO_OUT1, leds);
+	/*
+	    gpio_10 0
+	    gpio_13 1
+	    gpio_15 2
+	    gpio_14 3
+	*/	    
+    } else if (qoztmp->type == 0xb55b) {
+	qoz_outb(qoztmp,qoz_R_BRG_PCM_CFG,0x21); 
+    /* 0x01 g1 st1
+       0x02 g2 st2
+       0x04 g3 st3
+       0x08 g4 st4
+       0x10 r8 st5
+       0x20 r7 st6
+       0x40 r6 st7
+       0x80 r5 st8
+      */
+        if (qoztmp->leds[0] == 0) {
+		leds |= 0x01;
+        }
+        if (qoztmp->leds[1] == 0) {
+		leds |= 0x02;
+        }
+        if (qoztmp->leds[2] == 0) {
+		leds |= 0x04;
+        }
+        if (qoztmp->leds[3] == 0) {
+		leds |= 0x08;
+        }
+        if (qoztmp->leds[4] == 0) {
+		leds |= 0x10;
+        }
+        if (qoztmp->leds[5] == 0) {
+		leds |= 0x20;
+        }
+        if (qoztmp->leds[6] == 0) {
+		leds |= 0x40;
+        }
+        if (qoztmp->leds[7] == 0) {
+		leds |= 0x80;
+        }
+
+	ledw = leds << 24 | leds << 16 | leds << 8 | leds;
+	
+	qoz_outdw_io(qoztmp,0x4000, ledw);
+
+	qoz_outb(qoztmp,qoz_R_BRG_PCM_CFG,0x20); 
+
     }
     spin_unlock_irqrestore(&qoztmp->lock,flags);
 }
 
 void qoz_doWD(struct qoz_card *qoztmp) {
+    unsigned long flags;
     if (!qoztmp->wdp) {
 	return;
     }
-    if (qoztmp->wdp == 1) {
+    spin_lock_irqsave(&qoztmp->lock,flags);
+    qoz_outb(qoztmp,qoz_R_BRG_PCM_CFG,0x21); 
+	if (qoztmp->wdp == 1) {
 	    qoz_outdw_io(qoztmp,0x4000, qoz_WD_P2);
 	    qoztmp->wdp = 2;
-    } else {
+	} else {
 	    qoz_outdw_io(qoztmp,0x4000, qoz_WD_P1);
 	    qoztmp->wdp = 1;
-    }
-    qoz_inb_io(qoztmp,qoz_R_CHIP_ID);    
+	}
+	qoz_inb_io(qoztmp,qoz_R_CHIP_ID);    
+    qoz_outb(qoztmp,qoz_R_BRG_PCM_CFG,0x20); 
+    spin_unlock_irqrestore(&qoztmp->lock,flags);
 }
 
 void qoz_undoWD(struct qoz_card *qoztmp) {
     unsigned long flags;
 
-    spin_lock_irqsave(&qoztmp->lock,flags);
-    printk(KERN_INFO "qozap: Stopping hardware watchdog.\n");
-    qoz_outdw_io(qoztmp,0x4000, qoz_WD_P0);
-    qoztmp->wdp = 0;
-    qoz_inb_io(qoztmp,qoz_R_CHIP_ID);    
-    spin_unlock_irqrestore(&qoztmp->lock,flags);
+    if (qoztmp->wdp) {
+	printk(KERN_INFO "qozap: Stopping hardware watchdog.\n");
+	spin_lock_irqsave(&qoztmp->lock,flags);
+	qoz_outb(qoztmp,qoz_R_BRG_PCM_CFG,0x21); 
+	qoz_outdw_io(qoztmp,0x4000, qoz_WD_P0);
+	qoztmp->wdp = 0;
+	qoz_inb_io(qoztmp,qoz_R_CHIP_ID);    
+	qoz_outb(qoztmp,qoz_R_BRG_PCM_CFG,0x20); 
+	spin_unlock_irqrestore(&qoztmp->lock,flags);
+    }
 }
 
+void qoz_reset_pcm(struct qoz_card *qoztmp) {
+    qoz_outb(qoztmp,qoz_R_CIRM,0x20);
+    qoz_outb(qoztmp,qoz_R_CIRM,0x0); 
+    qoz_waitbusy(qoztmp);
+
+    if (pcmslave) {
+	qoz_outb(qoztmp,qoz_R_PCM_MD0, 0x90);
+	qoz_outb(qoztmp,qoz_R_PCM_MD1, 0x20);
+	qoz_outb(qoztmp,qoz_R_PCM_MD0, 0xA0);
+	qoz_outb(qoztmp,qoz_R_PCM_MD2, 0x4 | 0x8);
+    } else {
+	qoz_outb(qoztmp,qoz_R_PCM_MD0, 0x91);
+	qoz_outb(qoztmp,qoz_R_PCM_MD1, 0x20);
+    }
+}
+
 void qoz_resetCard(struct qoz_card *qoztmp) {
     unsigned long flags;
-    unsigned int i=0;
     spin_lock_irqsave(&(qoztmp->lock),flags);
     pci_write_config_word(qoztmp->pcidev, PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
     
@@ -192,6 +288,8 @@
     qoz_outb(qoztmp,qoz_R_CIRM,0x0); 
     qoz_waitbusy(qoztmp);
 
+    qoz_reset_pcm(qoztmp);
+
     // fifo reset
     qoz_outb(qoztmp,qoz_R_CIRM,0x10);
     qoz_outb(qoztmp,qoz_R_CIRM,0x0); 
@@ -206,6 +304,8 @@
     qoz_outb(qoztmp,qoz_R_PWM_MD,0xa0);
     if (qoztmp->type == 0xb552) {
 	qoz_outb(qoztmp,qoz_R_PWM0,0x19);
+    } else if (qoztmp->type == 0xb55b) {
+	qoz_outb(qoztmp,qoz_R_PWM0,0x19);
     } else {
 	qoz_outb(qoztmp,qoz_R_PWM0,0x1E);
     }
@@ -214,22 +314,14 @@
     qoz_outb(qoztmp,qoz_R_TI_WD, 0x2); 
     qoz_outb(qoztmp,qoz_R_IRQMSK_MISC, 0x2); 
 
-    if (pcmslave) {
-	qoz_outb(qoztmp,qoz_R_PCM_MD0, 0x0);
-    } else {
-	qoz_outb(qoztmp,qoz_R_PCM_MD0, 0x1);
-    }
 
-    for (i=0; i<256; i++) {
-	qoz_outb(qoztmp,qoz_R_SLOT, i);
-	qoz_outb(qoztmp,qoz_A_SL_CFG, 0x0);
-    }
-
     /* all state changes */
     qoz_outb(qoztmp,qoz_R_SCI_MSK, 0xff); 
 
     if (qoztmp->type == 0xb552) {
         qoz_outb(qoztmp,qoz_R_FIFO_MD,0x16);
+    } else if (qoztmp->type == 0xb55b) {
+        qoz_outb(qoztmp,qoz_R_FIFO_MD,0x16);
     } else {
         qoz_outb(qoztmp,qoz_R_FIFO_MD,0x26);
     }
@@ -242,7 +334,13 @@
 	if (qoztmp->type == 0x08b4) {
 	    qoz_outb(qoztmp,qoz_R_BRG_PCM_CFG,0x0); 
 	} else if (qoztmp->type == 0xb550) {
-	    qoz_outb(qoztmp,qoz_R_BRG_PCM_CFG,0x23); 
+	    qoz_outb(qoztmp,qoz_R_BRG_PCM_CFG,0x20); 
+	} else if (qoztmp->type == 0xb556) {
+	    qoz_outb(qoztmp,qoz_R_BRG_PCM_CFG,0x20); 
+	} else if (qoztmp->type == 0xb557) {
+	    qoz_outb(qoztmp,qoz_R_BRG_PCM_CFG,0x20); 
+	} else if (qoztmp->type == 0xb558) {
+	    qoz_outb(qoztmp,qoz_R_BRG_PCM_CFG,0x20); 
 	} else if (qoztmp->type == 0xb520) {
 	    qoz_outb(qoztmp,qoz_R_BRG_PCM_CFG,0x20); 
 	} else {
@@ -262,16 +360,20 @@
     qoztmp->leds[6] = 0x0;
     qoztmp->leds[7] = 0x0;
 
-    /* Finally enable IRQ output */
-//    qoz_outb(qoztmp,qoz_R_IRQ_CTRL, 0x8 | 0x1); 
     if (qoztmp->type == 0xb552) {
 	qoztmp->stports = 8;
+    } else if (qoztmp->type == 0xb55b) {
+	qoztmp->stports = 8;
+    } else if (qoztmp->type == 0xb556) {
+	qoztmp->stports = 2;
+    } else if (qoztmp->type == 0xb557) {
+	qoztmp->stports = 2;
     } else {
 	qoztmp->stports = 4;
     }
     qoztmp->ticks = 0;
     qoztmp->clicks = 0;
-    if (qoztmp->type == 0xb550) {
+    if ((qoztmp->type == 0xb550) || (qoztmp->type == 0xb556)) {
 	printk(KERN_INFO "qozap: Starting hardware watchdog.\n");
 	qoztmp->wdp = 2;
     } else {
@@ -279,19 +381,37 @@
     }
 
     qoz_outb(qoztmp,qoz_R_ST_SYNC,0x0);
+
+    /* IRQs off */
+    qoz_outb(qoztmp,qoz_R_IRQ_CTRL, 0); 
     
     spin_unlock_irqrestore(&(qoztmp->lock),flags);
 }
 
 void qoz_registerCard(struct qoz_card *qozcard) {
+    struct qoz_card *tmpcard = NULL;
     spin_lock(&registerlock);
+
     if (qozcard != NULL) {
-	qozcard->prev = NULL;
-	qozcard->next = qoz_dev_list;
-	if (qoz_dev_list) {
-	    qoz_dev_list->prev = qozcard;
+	if (!sort) {
+	    tmpcard = qoz_dev_list;
+	    if (tmpcard) {
+		while (tmpcard->next) {
+		    tmpcard = tmpcard->next;
+		}
+		tmpcard->next = qozcard;
+		qozcard->prev = tmpcard;
+	    } else {
+		qoz_dev_list = qozcard;
+	    }
+	} else {
+	    qozcard->prev = NULL;
+	    qozcard->next = qoz_dev_list;
+	    if (qoz_dev_list) {
+		qoz_dev_list->prev = qozcard;
+	    }
+	    qoz_dev_list = qozcard;
 	}
-	qoz_dev_list = qozcard;
 	qozcard->cardno = ++qoz_dev_count;
     } else {
 	printk(KERN_INFO "qozap: trying to register NULL card.\n");
@@ -309,6 +429,8 @@
 
     if (qoztmp->type == 0xb552) {
 	offset = 24;
+    } else if (qoztmp->type == 0xb55b) {
+	offset = 24;
     } else {
 	offset = 28;
     }
@@ -373,6 +495,8 @@
 
     if (qoztmp->type == 0xb552) {
 	offset = 24;
+    } else if (qoztmp->type == 0xb55b) {
+	offset = 24;
     } else {
 	offset = 28;
     }
@@ -402,7 +526,7 @@
     while ((oz1 != z1) && (oz2 != z2)) {
         oz1 = z1;
         oz2 = z2;
-	if (qoztmp->type != 0xb552) {
+	if ((qoztmp->type != 0xb552) && (qoztmp->type != 0xb55b)){
     	    z1 = qoz_inw(qoztmp,qoz_A_Z1) & 0x7ff;
 	    z2 = qoz_inw(qoztmp,qoz_A_Z2) & 0x7ff;
 	} else {
@@ -411,7 +535,7 @@
 	}
     }
     
-    if (qoztmp->type == 0xb552) {
+    if ((qoztmp->type == 0xb552)|| (qoztmp->type == 0xb55b)) {
 	len = z1 - z2;
 	if (len < 0) {
 	    len += qoz_DFIFO_SIZE8;
@@ -495,8 +619,8 @@
     		data = qoz_inb(qoztmp,qoz_A_FIFO_DATA0);
 	    }
 	    qoztmp->clicks++;
-	    if ((qoztmp->clicks > 50) && (debug > 0)) {
-		printk(KERN_CRIT "qozap: dropped audio card %d cardid %d bytes %d z1 %d z2 %d\n", qoztmp->cardno, qoztmp->cardID, mumbojumbo, z1, z2);
+	    if (((qoztmp->clicks > 50) || (debug > 5)) && (mumbojumbo > 0)) {
+		printk(KERN_CRIT "qozap: dropped audio card %d cardid %d bytes %d z1 %d z2 %d fifo %d\n", qoztmp->cardno, qoztmp->cardID, mumbojumbo, z1, z2, fifo);
 		qoztmp->clicks = 0;
 	    }
 	}
@@ -524,9 +648,8 @@
     return 0;
 }
 
-static void qoz_assign(struct qoz_card *qoztmp, int src_span, int src_chan, int dst_span, int dst_chan) {
+static void qoz_assign(struct qoz_card *qoztmp, int src_span, int src_chan, int dst_span, int dst_chan, int timeslot, int use_pcm_bus) {
     unsigned long flags;
-    int timeslot = src_span * 2 + (src_chan - 1);
     int dst_fifo = dst_span * 2 + (dst_chan - 1); 
     int src_fifo = src_span * 2 + (src_chan - 1); 
     int src_hfc_chan = src_span * 4 + (src_chan - 1);
@@ -557,10 +680,10 @@
     spin_unlock_irqrestore(&qoztmp->lock, flags);
 }
 
-static void qoz_unassign(struct qoz_card *qoztmp, int span, int chan) {
+static void qoz_unassign(struct qoz_card *qoztmp, int span, int chan, int timeslot) {
     unsigned long flags;
 
-    int timeslot = span * 2 + (chan - 1);
+//    int timeslot = span * 2 + (chan - 1);
     int fifo = span * 2 + (chan - 1);
     int hfc_chan = span * 4 + (chan - 1);
 
@@ -595,36 +718,48 @@
 static int ztqoz_dacs(struct zt_chan *dst, struct zt_chan *src)
 {
 	struct qoz_card *qoztmp = NULL;
-	if (!dacs) return 0;
+	int use_pcm_bus = 0;
+	int timeslot = 0;
+	if (!dacs) return -1;
 
-	if (src) { 
+	if (src) {
 	    qoztmp = src->pvt;
-	}
-	if (src && (src->pvt != dst->pvt)) {
-		/* cross card bridging */
-		if (debug)
-		    printk("Not Assigning %d/%d -> %d/%d, different cards!\n", src->span->offset, src->chanpos, dst->span->offset, dst->chanpos);
-		return -1;
-	}
 
-	if (src) {
-		if ((src->chanpos == 3) || (dst->chanpos == 3)) {
+	    if (src->pvt != dst->pvt) {
+		if (dacs == 2) {
+		    use_pcm_bus = 1;
+		    timeslot = src->channo;
 		    if (debug)
-			printk("Not Assigning D-channel %d/%d -> %d/%d!\n", src->span->offset, src->chanpos, dst->span->offset, dst->chanpos);
+			printk("qozap: Assigning channel %d/%d -> %d/%d, timeslot %d, different cards!\n", src->span->offset, src->chanpos, dst->span->offset, dst->chanpos, timeslot);
 		} else {
 		    if (debug)
-			printk("Assigning channel %d/%d -> %d/%d!\n", src->span->offset, src->chanpos, dst->span->offset, dst->chanpos);
-		    qoz_assign(qoztmp, src->span->offset, src->chanpos, dst->span->offset, dst->chanpos);
+			printk("qozap: Not Assigning %d/%d -> %d/%d, different cards!\n", src->span->offset, src->chanpos, dst->span->offset, dst->chanpos);
+		    return -1;
 		}
+	    } else {
+		use_pcm_bus = 0;
+//		timeslot = src->span->offset * 2 + (src->chanpos);
+		timeslot = src->channo;
+	        if (debug)
+	    	    printk("qozap: Assigning channel %d/%d -> %d/%d, timeslot %d, same card!\n", src->span->offset, src->chanpos, dst->span->offset, dst->chanpos, timeslot);
+	    }
+
+	    if ((src->chanpos == 3) || (dst->chanpos == 3)) {
+	        if (debug)
+			printk("qozap: Not Assigning D-channel %d/%d -> %d/%d!\n", src->span->offset, src->chanpos, dst->span->offset, dst->chanpos);
+	    } else {
+		qoz_assign(qoztmp, src->span->offset, src->chanpos, dst->span->offset, dst->chanpos, timeslot, use_pcm_bus);
+	    }
 	} else {
 		qoztmp = dst->pvt;
 		if (dst->chanpos == 3) {
 		    if (debug)
-			printk("Not Unassigning D-channel %d/%d!\n", dst->span->offset, dst->chanpos);
+			printk("qozap: Not Unassigning D-channel %d/%d!\n", dst->span->offset, dst->chanpos);
 		} else {
-		    qoz_unassign(qoztmp, dst->span->offset, dst->chanpos);
+		    timeslot = dst->channo;
+		    qoz_unassign(qoztmp, dst->span->offset, dst->chanpos, timeslot);
 		    if (debug)
-			printk("Unassigning channel %d/%d!\n", dst->span->offset, dst->chanpos);
+			printk("qozap: Unassigning channel %d/%d, timeslot %d!\n", dst->span->offset, dst->chanpos, timeslot);
 		}
 	}
 	return 0;
@@ -632,22 +767,32 @@
 
 static void qoz_resync(struct qoz_card *qoztmp) {
     int i=0;
-    int best=99;
+    int best=9999;
     int src=-1;
 
+    if (pcmslave) return;
+
     for (i=0; i<qoztmp->stports; i++){
 	if (qoztmp->st[i].l1up && (qoztmp->st_sync[i] > 0) && (qoztmp->st_sync[i] < best)) {
 	    best = qoztmp->st_sync[i];
 	    src = i;
 	}
     }
+    if (src < 0) {
+	for (i=0; i<qoztmp->stports; i++){
+	    if ((qoztmp->st_sync[i] > 0) && (qoztmp->st_sync[i] < best)) {
+		best = qoztmp->st_sync[i];
+	        src = i;
+	    }
+	}
+    }
     if (src == qoztmp->syncsrc)
 	return;
     if (src >= 0) {
 	qoztmp->syncsrc = src;
 	qoz_outb(qoztmp, qoz_R_ST_SYNC, src | 0x08);
 	if (debug > 2)
-	    printk(KERN_INFO "qozap: Sync source changed to span %d\n", src + 1);
+	    printk(KERN_INFO "qozap: card %d Sync source changed to span %d\n", qoztmp->cardno, src + 1);
     }
 }
 
@@ -748,11 +893,7 @@
     } 
 }
 
-#ifdef LINUX26
-static irqreturn_t qoz_interrupt(int irq, void *dev_id, struct pt_regs *regs) {
-#else
-static void qoz_interrupt(int irq, void *dev_id, struct pt_regs *regs) {
-#endif
+ZAP_IRQ_HANDLER(qoz_interrupt) {
     struct qoz_card *qoztmp = dev_id;
     unsigned long flags;
     unsigned char irq_misc,irq_sci,status,l1state,irq_foview,fi;
@@ -801,10 +942,12 @@
     /* state machine irq */
     if (irq_sci != 0) {
 	if (debug > 1) {
-	    printk(KERN_INFO "R_BERT_STA = %#x\n", qoz_inb(qoztmp, qoz_R_BERT_STA) & 7);
+	    printk(KERN_INFO "qozap: card %d R_BERT_STA = %#x\n", qoztmp->cardno, qoz_inb(qoztmp, qoz_R_BERT_STA) & 7);
 	}
 	if (qoztmp->type == 0xb552) {
 	    offset = 24;
+	} else if (qoztmp->type == 0xb55b) {
+	    offset = 24;
         } else {
 	    offset = 28;
 	}
@@ -814,7 +957,7 @@
 		qoz_outb(qoztmp,qoz_R_ST_SEL,st);
 		l1state = qoz_inb(qoztmp,qoz_A_ST_RD_STA) & 0xf;
 		if (debug > 1) {
-		    printk(KERN_INFO "A_ST_RD_STA = %#x\n", qoz_inb(qoztmp, qoz_A_ST_RD_STA));
+		    printk(KERN_INFO "qozap: card %d span %d A_ST_RD_STA = %#x\n", qoztmp->cardno, st+1, qoz_inb(qoztmp, qoz_A_ST_RD_STA));
 		}
 		qoztmp->st[st].layer1state = l1state;
 		if (qoztmp->st[st].nt_mode == 1) {
@@ -826,7 +969,9 @@
 			// keep layer1 up!
 			if (qoztmp->stports == 8) {
 			    sprintf(qoztmp->spans[st].desc,"octoBRI PCI ISDN Card %d Span %d [NT] Layer 1 ACTIVATED (G%d)",qoztmp->cardno ,st + 1, l1state);
-			} else {
+			} else if (qoztmp->stports == 2) {
+			    sprintf(qoztmp->spans[st].desc,"duoBRI PCI ISDN Card %d Span %d [NT] (cardID %d) Layer 1 ACTIVATED (G%d)",qoztmp->cardno ,st + 1,qoztmp->cardID, l1state);
+			} else{
 			    sprintf(qoztmp->spans[st].desc,"quadBRI PCI ISDN Card %d Span %d [NT] (cardID %d) Layer 1 ACTIVATED (G%d)",qoztmp->cardno ,st + 1,qoztmp->cardID, l1state);
 			}
 			qoz_outb(qoztmp,qoz_A_ST_WR_STA,3 | 0x10 );
@@ -835,6 +980,8 @@
 			qoztmp->st[st].l1up = 0;
 			if (qoztmp->stports == 8) {
 			    sprintf(qoztmp->spans[st].desc,"octoBRI PCI ISDN Card %d Span %d [NT] Layer 1 DEACTIVATED (G%d)",qoztmp->cardno ,st + 1, l1state);
+			} else if (qoztmp->stports == 2) {
+			    sprintf(qoztmp->spans[st].desc,"duoBRI PCI ISDN Card %d Span %d [NT] (cardID %d) Layer 1 DEACTIVATED (G%d)",qoztmp->cardno ,st + 1,qoztmp->cardID, l1state);
 			} else {
 			    sprintf(qoztmp->spans[st].desc,"quadBRI PCI ISDN Card %d Span %d [NT] (cardID %d) Layer 1 DEACTIVATED (G%d)",qoztmp->cardno ,st + 1,qoztmp->cardID, l1state);
 			}
@@ -865,6 +1012,8 @@
 			qoztmp->leds[st] = 0;
 			if (qoztmp->stports == 8) {
 			    sprintf(qoztmp->spans[st].desc,"octoBRI PCI ISDN Card %d Span %d [TE] Layer 1 DEACTIVATED (F%d)",qoztmp->cardno ,st + 1, l1state);
+			} else if (qoztmp->stports == 2) {
+			    sprintf(qoztmp->spans[st].desc,"duoBRI PCI ISDN Card %d Span %d [TE] (cardID %d) Layer 1 DEACTIVATED (F%d)",qoztmp->cardno ,st + 1,qoztmp->cardID, l1state);
 			} else {
 			    sprintf(qoztmp->spans[st].desc,"quadBRI PCI ISDN Card %d Span %d [TE] (cardID %d) Layer 1 DEACTIVATED (F%d)",qoztmp->cardno ,st + 1,qoztmp->cardID, l1state);
 			}
@@ -882,6 +1031,8 @@
 			qoztmp->leds[st] = 1;
 			if (qoztmp->stports == 8) {
 			    sprintf(qoztmp->spans[st].desc,"octoBRI PCI ISDN Card %d Span %d [TE] Layer 1 ACTIVATED (F%d)",qoztmp->cardno ,st + 1, l1state);
+			} else if (qoztmp->stports == 2) {
+			    sprintf(qoztmp->spans[st].desc,"duoBRI PCI ISDN Card %d Span %d [TE] (cardID %d) Layer 1 ACTIVATED (F%d)",qoztmp->cardno ,st + 1,qoztmp->cardID, l1state);
 			} else {
 			    sprintf(qoztmp->spans[st].desc,"quadBRI PCI ISDN Card %d Span %d [TE] (cardID %d) Layer 1 ACTIVATED (F%d)",qoztmp->cardno ,st + 1,qoztmp->cardID, l1state);
 			}
@@ -892,8 +1043,11 @@
 			qoztmp->st[st].t4 = 0;
 		    } else {
 			qoztmp->st[st].l1up = 0;
+			qoztmp->leds[st] = 0;
 			if (qoztmp->stports == 8) {
 			    sprintf(qoztmp->spans[st].desc,"octoBRI PCI ISDN Card %d Span %d [TE] Layer 1 DEACTIVATED (F%d)",qoztmp->cardno ,st + 1, l1state);
+			} else if (qoztmp->stports == 2) {
+			    sprintf(qoztmp->spans[st].desc,"duoBRI PCI ISDN Card %d Span %d [TE] (cardID %d) Layer 1 DEACTIVATED (F%d)",qoztmp->cardno ,st + 1,qoztmp->cardID, l1state);
 			} else {
 			    sprintf(qoztmp->spans[st].desc,"quadBRI PCI ISDN Card %d Span %d [TE] (cardID %d) Layer 1 DEACTIVATED (F%d)",qoztmp->cardno ,st + 1,qoztmp->cardID, l1state);
 			}    
@@ -977,7 +1131,7 @@
 	/* fifo irq */
 	spin_lock_irqsave(&(qoztmp->lock), flags);
 	irq_foview = qoz_inb(qoztmp,qoz_R_IRQ_OVIEW);
-        if (qoztmp->type == 0xb552) {
+        if ((qoztmp->type == 0xb552) || (qoztmp->type == 0xb55b)) {
 	    if (irq_foview & 0x60) {
 		offset = 0;
 		fi = qoz_inb(qoztmp,qoz_R_IRQ_FIFO_BL6);
@@ -1109,12 +1263,25 @@
 	return 0;
     }
 
+    if (pcmslave && !span->offset) {
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout((100 * HZ) / 1000);
+    }
+
     spin_lock_irqsave(&qoztmp->lock,flags);
+    if (pcmslave && !span->offset) {
+	if (debug) 
+	    printk(KERN_INFO "qozap: resetting PCM interface to slave mode\n");
+	qoz_reset_pcm(qoztmp);
+    }
+
     // irqs off
     qoz_outb(qoztmp,qoz_R_IRQ_CTRL, 0); 
 
     if (qoztmp->type == 0xb552) {
 	offset = 24;
+    } else if (qoztmp->type == 0xb55b) {
+	offset = 24;
     } else {
 	offset = 28;
     }
@@ -1246,6 +1413,8 @@
     // turn off irqs for all fifos
     if (qoztmp->type == 0xb552) {
 	offset = 24;
+    } else if (qoztmp->type == 0xb55b) {
+	offset = 24;
     } else {
 	offset = 28;
     }
@@ -1324,13 +1493,19 @@
     
     for (s=0; s < qoztmp->stports; s++) {
 	memset(&qoztmp->spans[s],0,sizeof(struct zt_span));
-	sprintf(qoztmp->spans[s].name,"ztqoz/%d/%d",qoz_dev_count + 1,s + 1);
+	sprintf(qoztmp->spans[s].name,"ztqoz/%d/%d",qoztmp->cardno ,s + 1);
 	if (qoztmp->stports == 8) {
 	    if (qoztmp->st[s].nt_mode == 1){
 		sprintf(qoztmp->spans[s].desc,"octoBRI PCI ISDN Card %d Span %d [NT]",qoztmp->cardno,s + 1);
 	    } else {
 		sprintf(qoztmp->spans[s].desc,"octoBRI PCI ISDN Card %d Span %d [TE]",qoztmp->cardno,s + 1);
 	    }
+	} else 	if (qoztmp->stports == 2) {
+	    if (qoztmp->st[s].nt_mode == 1){
+		sprintf(qoztmp->spans[s].desc,"duoBRI PCI ISDN Card %d Span %d [NT]",qoztmp->cardno,s + 1);
+	    } else {
+		sprintf(qoztmp->spans[s].desc,"duoBRI PCI ISDN Card %d Span %d [TE]",qoztmp->cardno,s + 1);
+	    }
 	} else {
 	    if (qoztmp->cardID < 0xff) {
 		if (qoztmp->st[s].nt_mode == 1){
@@ -1368,9 +1543,9 @@
 
 	for (i=0; i < qoztmp->spans[s].channels; i++) {
 	    memset(&(qoztmp->chans[s][i]),0x0,sizeof(struct zt_chan));
-	    sprintf(qoztmp->chans[s][i].name,"ztqoz%d/%d/%d",qoz_dev_count + 1,s + 1,i + 1);
+	    sprintf(qoztmp->chans[s][i].name,"ztqoz%d/%d/%d",qoztmp->cardno,s + 1,i + 1);
 	    qoztmp->chans[s][i].pvt = qoztmp;
-	    qoztmp->chans[s][i].sigcap =  ZT_SIG_EM | ZT_SIG_CLEAR | ZT_SIG_FXSLS | ZT_SIG_FXSGS | ZT_SIG_FXSKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_FXOKS | ZT_SIG_CAS | ZT_SIG_SF;
+	    qoztmp->chans[s][i].sigcap =  ZT_SIG_CLEAR | ZT_SIG_DACS;
 	    qoztmp->chans[s][i].chanpos = i + 1; 
 	}
 
@@ -1461,19 +1636,16 @@
 	
 	pci_write_config_word(qoztmp->pcidev, PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
 
-	// disable ints
 	qoz_outb(qoztmp,qoz_R_IRQ_CTRL, 0); 
 
-	if (pcidid == PCI_DEVICE_ID_CCD_M) {
-	    qoztmp->stports = 8;
-	} else {
-	    qoztmp->stports = 4;
-	}
+	qoztmp->type = tmp->subsystem_device;
+	qoz_resetCard(qoztmp);
 	
 
         if ((tmp->subsystem_device==0xb520) && (pcidid == PCI_DEVICE_ID_CCD_M4)) {
 	//    printk(KERN_INFO "MODES = %#x.\n",modes);
 	    qoz_outb(qoztmp,qoz_R_GPIO_SEL,0x80 | 0x40);
+	    qoz_outb(qoztmp,qoz_R_GPIO_EN1,0x00);
 	    dips = (qoz_inb(qoztmp,qoz_R_GPIO_IN1) >> 5);
 	    cid = 7;
 	    for (i=0;i<3;i++) {
@@ -1483,15 +1655,76 @@
 	    }
 	//	printk(KERN_INFO "DIPS = %#x CID= %#x\n",dips,cid);
         } else if ((tmp->subsystem_device==0xb550) && (pcidid == PCI_DEVICE_ID_CCD_M4)) {
+		/* quadBRI 2.0 */
 	//    printk(KERN_INFO "MODES = %#x.\n",modes);
-	    dips = ~(qoz_inb(qoztmp,qoz_R_GPI_IN3) & 7);
-	    cid = 0;
-	    for (i=0;i<3;i++) {
-	        if ((dips & (1 << i)) != 0) {
-	    	cid += (1 << i);
-	        }
-	    }
-	printk(KERN_INFO "DIPS = %#x CID= %#x\n",dips,cid);
+		qoz_outb(qoztmp,qoz_R_GPIO_SEL,0xF0);
+		qoz_outb(qoztmp,qoz_R_GPIO_EN0,0x00);
+		qoz_outb(qoztmp,qoz_R_GPIO_EN1,0x00);
+//		dips = qoz_inb(qoztmp,qoz_R_GPIO_IN1) >> 5;
+		dips = ((qoz_inb(qoztmp,qoz_R_GPI_IN3) & 80) >> 1) | ((qoz_inb(qoztmp,qoz_R_GPI_IN3) & 8) << 2) | qoz_inb(qoztmp,qoz_R_GPIO_IN1);
+
+		cid = 0;
+		for (i=0;i<3;i++) {
+	    	    if ((dips & (1 << i)) == 0) {
+	    		cid += (1 << i);
+		    }
+		}
+
+        } else if ((tmp->subsystem_device==0xb556) && (pcidid == PCI_DEVICE_ID_CCD_M4)) {
+		/* duoBRI */
+
+		/* gpi27 1 gpi23 2 */
+		qoz_outb(qoztmp,qoz_R_GPIO_SEL,0xf0);
+		qoz_outb(qoztmp,qoz_R_GPIO_EN0,0x00);
+		qoz_outb(qoztmp,qoz_R_GPIO_EN1,0x00);
+
+/*		dips = qoz_inb_io(qoztmp,0x4000);
+		dips = qoz_inb_io(qoztmp,0x4000);
+		dips = qoz_inb_io(qoztmp,0x4000);
+		dips = qoz_inb_io(qoztmp,0x4000);
+
+		qoz_outw_io(qoztmp,0x0,0x0);  */
+
+
+        } else if ((tmp->subsystem_device==0xb558) && (pcidid == PCI_DEVICE_ID_CCD_M4)) {
+		/* quadBRI minipCI */
+		qoz_outb(qoztmp,qoz_R_GPIO_SEL,0xF0);
+		qoz_outb(qoztmp,qoz_R_GPIO_EN0,0x00);
+		qoz_outb(qoztmp,qoz_R_GPIO_EN1,0x00);
+		dips = qoz_inb(qoztmp,qoz_R_GPIO_IN1) >> 5;
+/*	    printk(KERN_INFO "gpio_in1 %#x\n", qoz_inb(qoztmp,qoz_R_GPIO_IN1));
+
+	    printk(KERN_INFO "gpi_in2 %#x\n", qoz_inb(qoztmp,qoz_R_GPI_IN2));
+	    printk(KERN_INFO "dip1 %#x\n", (qoz_inb(qoztmp,qoz_R_GPI_IN3) & 80) >> 7);
+	    printk(KERN_INFO "gpi_in3 %#x\n", qoz_inb(qoztmp,qoz_R_GPI_IN3));
+	    printk(KERN_INFO "dip2 %#x\n", (qoz_inb(qoztmp,qoz_R_GPI_IN3) & 8) >> 3); >*/
+		cid = 0;
+		for (i=0;i<3;i++) {
+	    	    if ((dips & (1 << i)) != 0) {
+	    		cid += (1 << i);
+		    }
+		}
+//	    printk(KERN_INFO "DIPS = %#x CID= %#x\n",dips,cid);
+
+	} else if ((tmp->subsystem_device==0xb55b) && (pcidid == PCI_DEVICE_ID_CCD_M)){
+		qoz_outb(qoztmp,qoz_R_BRG_PCM_CFG,0x21); 
+
+		dips = ~qoz_inb_io(qoztmp,0x4000);
+		dips = ~qoz_inb_io(qoztmp,0x4000);
+		dips = ~qoz_inb_io(qoztmp,0x4000);
+		dips = ~qoz_inb_io(qoztmp,0x4000);
+
+		dips &= 0x3F;
+		qoz_outw_io(qoztmp,0x0,0x0); 
+
+		cid = 0;
+		for (i=0;i<6;i++) {
+	    	    if ((dips & (1 << i)) != 0) {
+	    		cid += (1 << i);
+		    }
+		}
+		qoz_outb(qoztmp,qoz_R_BRG_PCM_CFG,0x20); 
+		printk(KERN_CRIT "dips = %#x cid = %d\n", dips, cid);
         } else {
 	    cid = 0xff;
         }
@@ -1500,14 +1733,38 @@
     	    if ((tmp->subsystem_device==0xb520) && (pcidid == PCI_DEVICE_ID_CCD_M4)) {
 		modes = qoz_inb(qoztmp,qoz_R_GPI_IN3) >> 4;
     	    } else if ((tmp->subsystem_device==0xb550) && (pcidid == PCI_DEVICE_ID_CCD_M4)) {
-		qoz_outb(qoztmp,qoz_R_GPIO_SEL,0xff);
+		qoz_outb(qoztmp,qoz_R_GPIO_SEL,0xf0);
 		qoz_outb(qoztmp,qoz_R_GPIO_EN0,0x00);
-		printk(KERN_CRIT "gpio_in0 %#x \n", qoz_inb(qoztmp,qoz_R_GPIO_IN0));
-		printk(KERN_CRIT "gpio_in1 %#x \n", qoz_inb(qoztmp,qoz_R_GPIO_IN1));
-		printk(KERN_CRIT "gpi_in1 %#x \n", qoz_inb(qoztmp,qoz_R_GPI_IN1));
-		printk(KERN_CRIT "gpi_in2 %#x \n", qoz_inb(qoztmp,qoz_R_GPI_IN2));
-		printk(KERN_CRIT "gpi_in3 %#x \n", qoz_inb(qoztmp,qoz_R_GPI_IN3));
+		if (debug) {
+		    printk(KERN_CRIT "gpio_in0 %#x \n", qoz_inb(qoztmp,qoz_R_GPIO_IN0));
+		    printk(KERN_CRIT "gpio_in1 %#x \n", qoz_inb(qoztmp,qoz_R_GPIO_IN1));
+		    printk(KERN_CRIT "gpi_in1 %#x \n", qoz_inb(qoztmp,qoz_R_GPI_IN1));
+		    printk(KERN_CRIT "gpi_in2 %#x \n", qoz_inb(qoztmp,qoz_R_GPI_IN2));
+		    printk(KERN_CRIT "gpi_in3 %#x \n", qoz_inb(qoztmp,qoz_R_GPI_IN3));
+		}
 		modes = qoz_inb(qoztmp,qoz_R_GPI_IN3) >> 4;	    
+    	    } else if ((tmp->subsystem_device==0xb558) && (pcidid == PCI_DEVICE_ID_CCD_M4)) {
+		qoz_outb(qoztmp,qoz_R_GPIO_SEL,0xf0);
+		qoz_outb(qoztmp,qoz_R_GPIO_EN0,0x00);
+		if (debug) {
+		    printk(KERN_CRIT "gpio_in0 %#x \n", qoz_inb(qoztmp,qoz_R_GPIO_IN0));
+		    printk(KERN_CRIT "gpio_in1 %#x \n", qoz_inb(qoztmp,qoz_R_GPIO_IN1));
+	    	    printk(KERN_CRIT "gpi_in1 %#x \n", qoz_inb(qoztmp,qoz_R_GPI_IN1));
+		    printk(KERN_CRIT "gpi_in2 %#x \n", qoz_inb(qoztmp,qoz_R_GPI_IN2));
+		    printk(KERN_CRIT "gpi_in3 %#x \n", qoz_inb(qoztmp,qoz_R_GPI_IN3));
+		}
+		modes = qoz_inb(qoztmp,qoz_R_GPI_IN3) >> 4;	    
+    	    } else if ((tmp->subsystem_device==0xb556) && (pcidid == PCI_DEVICE_ID_CCD_M4)) {
+		qoz_outb(qoztmp,qoz_R_GPIO_SEL,0xf0);
+		qoz_outb(qoztmp,qoz_R_GPIO_EN0,0x00);
+		if (debug) {
+		    printk(KERN_CRIT "gpio_in0 %#x \n", qoz_inb(qoztmp,qoz_R_GPIO_IN0));
+		    printk(KERN_CRIT "gpio_in1 %#x \n", qoz_inb(qoztmp,qoz_R_GPIO_IN1));
+		    printk(KERN_CRIT "gpi_in1 %#x \n", qoz_inb(qoztmp,qoz_R_GPI_IN1));
+		    printk(KERN_CRIT "gpi_in2 %#x \n", qoz_inb(qoztmp,qoz_R_GPI_IN2));
+		    printk(KERN_CRIT "gpi_in3 %#x \n", qoz_inb(qoztmp,qoz_R_GPI_IN3));
+		}
+		modes = qoz_inb(qoztmp,qoz_R_GPI_IN3) >> 4;
 	    } else {
 		modes = 0; // assume TE mode
 	    }
@@ -1523,21 +1780,44 @@
 		        "qozap: CologneChip HFC-4S evaluation board configured at io port %#x IRQ %d HZ %d\n",
 		          (u_int) qoztmp->ioport,
 		        qoztmp->irq, HZ);
+		        totalBRIs += 4;
 		    break;
 		case 0xb520:
 			printk(KERN_INFO
 		        "qozap: Junghanns.NET quadBRI card configured at io port %#x IRQ %d HZ %d CardID %d\n",
 		          (u_int) qoztmp->ioport,
 		        qoztmp->irq, HZ, cid);
+		        totalBRIs += 4;
 		    break;
 		case 0xb550:
 			printk(KERN_INFO
 		        "qozap: Junghanns.NET quadBRI (Version 2.0) card configured at io port %#x IRQ %d HZ %d CardID %d\n",
 		          (u_int) qoztmp->ioport,
 		        qoztmp->irq, HZ, cid);
+		        totalBRIs += 4;
 		    break;
+		case 0xb556:
+			printk(KERN_INFO
+		        "qozap: Junghanns.NET duoBRI card configured at io port %#x IRQ %d HZ %d CardID %d\n",
+		          (u_int) qoztmp->ioport,
+		        qoztmp->irq, HZ, cid);
+		        totalBRIs += 2;
+		    break;
+		case 0xb557:
+			printk(KERN_INFO
+		        "qozap: Junghanns.NET duoBRI miniPCI card configured at io port %#x IRQ %d HZ %d CardID %d\n",
+		          (u_int) qoztmp->ioport,
+		        qoztmp->irq, HZ, cid);
+		        totalBRIs += 2;
+		    break;
+		case 0xb558:
+			printk(KERN_INFO
+		        "qozap: Junghanns.NET quadBRI miniPCI card configured at io port %#x IRQ %d HZ %d CardID %d\n",
+		          (u_int) qoztmp->ioport,
+		        qoztmp->irq, HZ, cid);
+		        totalBRIs += 4;
+		    break;
 	    } 
-	    totalBRIs += 4;
 	} else {
 	    switch (tmp->subsystem_device) {
 		case 0xb552:
@@ -1546,6 +1826,12 @@
 		       (u_int) qoztmp->ioport,
 		       qoztmp->irq, HZ);
 	        break;
+		case 0xb55b:
+		    printk(KERN_INFO
+		       "qozap: Junghanns.NET octoBRI (Version 2.0) card configured at io port %#x IRQ %d HZ %d\n",
+		       (u_int) qoztmp->ioport,
+		       qoztmp->irq, HZ);
+	        break;
 		default:
 		    printk(KERN_INFO
 		       "qozap: wtf\n");
@@ -1629,7 +1915,6 @@
     tmpcard = qoz_dev_list;
     while (tmpcard != NULL) {
 	ztqoz_initialize(tmpcard);
-	qoz_resetCard(tmpcard);
 	tmpcard = tmpcard->next;
     }
     return 0;
@@ -1641,12 +1926,14 @@
     qoz_findCards(PCI_DEVICE_ID_CCD_M4);
     multi_qoz = NULL;
     qoz_findCards(PCI_DEVICE_ID_CCD_M);
-    qoz_sortCards();
+    if (sort) {
+	qoz_sortCards();
+    }
     qoz_zapCards();
     if (qoz_dev_count == 0) {
 	printk(KERN_INFO "qozap: no multiBRI cards found.\n");
     } else {
-	printk(KERN_INFO "qozap: %d multiBRI card(s) in this box, %d BRI ports total, bloop %d, pcmslave %d.\n",qoz_dev_count, totalBRIs, bloop, pcmslave);
+	printk(KERN_INFO "qozap: %d multiBRI card(s) in this box, %d BRI ports total, bloop %d, pcmslave %d, dacs %d.\n",qoz_dev_count, totalBRIs, bloop, pcmslave, dacs);
     }
     return 0;
 }
@@ -1657,6 +1944,7 @@
     tmplist = qoz_dev_list;
     while (tmplist != NULL) {
 	tmplist->dead = 1;
+	qoz_resetCard(tmplist);
 	qoz_undoWD(tmplist);
 	qoz_shutdownCard(tmplist);
 	tmplist = tmplist->next;
@@ -1681,6 +1969,7 @@
 module_param(bloop, int, 0600);
 module_param(debug, int, 0600);
 module_param(dacs, int, 0600);
+module_param(sort, int, 0600);
 #else
 MODULE_PARM(doubleclock,"i");
 MODULE_PARM(ports,"i");
@@ -1688,6 +1977,7 @@
 MODULE_PARM(bloop,"i");
 MODULE_PARM(debug,"i");
 MODULE_PARM(dacs,"i");
+MODULE_PARM(sort,"i");
 #endif
 
 

Added: zaptel/trunk/qozap/zapata.conf.duoBRI
===================================================================
--- zaptel/trunk/qozap/zapata.conf.duoBRI	                        (rev 0)
+++ zaptel/trunk/qozap/zapata.conf.duoBRI	2007-08-05 11:43:22 UTC (rev 3905)
@@ -0,0 +1,43 @@
+;
+; Zapata telephony interface
+;
+; Configuration file
+
+[channels]
+;
+; Default language
+;
+;language=en
+;
+; Default context
+;
+;
+switchtype = euroisdn
+
+; p2mp TE mode (for connecting ISDN lines in point-to-multipoint mode)
+signalling = bri_cpe_ptmp
+; p2p TE mode (for connecting ISDN lines in point-to-point mode)
+;signalling = bri_cpe
+; p2mp NT mode (for connecting ISDN phones in point-to-multipoint mode)
+;signalling = bri_net_ptmp
+; p2p NT mode (for connecting an ISDN pbx in point-to-point mode)
+;signalling = bri_net
+
+pridialplan = local
+prilocaldialplan = dynamic
+nationalprefix = 0
+internationalprefix = 00
+
+priindication = passthrough
+
+echocancel = yes
+
+context=demo
+group = 1
+; S/T port 1
+channel => 1-2
+
+group = 2
+; S/T port 2
+channel => 4-5
+

Modified: zaptel/trunk/qozap/zaptel.conf
===================================================================
--- zaptel/trunk/qozap/zaptel.conf	2007-08-05 11:21:06 UTC (rev 3904)
+++ zaptel/trunk/qozap/zaptel.conf	2007-08-05 11:43:22 UTC (rev 3905)
@@ -4,8 +4,8 @@
 # most of the values should be bogus because we are not really zaptel
 span=1,1,3,ccs,ami
 span=2,2,3,ccs,ami
-span=3,0,3,ccs,ami
-span=4,0,3,ccs,ami
+span=3,3,3,ccs,ami
+span=4,4,3,ccs,ami
 
 bchan=1,2
 dchan=3

Added: zaptel/trunk/qozap/zaptel.conf.duoBRI
===================================================================
--- zaptel/trunk/qozap/zaptel.conf.duoBRI	                        (rev 0)
+++ zaptel/trunk/qozap/zaptel.conf.duoBRI	2007-08-05 11:43:22 UTC (rev 3905)
@@ -0,0 +1,11 @@
+loadzone=nl
+defaultzone=nl
+# qozap span definitions
+# most of the values should be bogus because we are not really zaptel
+span=1,1,3,ccs,ami
+span=2,2,3,ccs,ami
+
+bchan=1,2
+dchan=3
+bchan=4,5
+dchan=6

Modified: zaptel/trunk/qozap/zaptel.conf.octoBRI
===================================================================
--- zaptel/trunk/qozap/zaptel.conf.octoBRI	2007-08-05 11:21:06 UTC (rev 3904)
+++ zaptel/trunk/qozap/zaptel.conf.octoBRI	2007-08-05 11:43:22 UTC (rev 3905)
@@ -3,13 +3,13 @@
 # qozap span definitions
 # most of the values should be bogus because we are not really zaptel
 span=1,1,3,ccs,ami
-span=2,0,3,ccs,ami
-span=3,0,3,ccs,ami
-span=4,0,3,ccs,ami
-span=5,1,3,ccs,ami
-span=6,0,3,ccs,ami
-span=7,0,3,ccs,ami
-span=8,0,3,ccs,ami
+span=2,2,3,ccs,ami
+span=3,3,3,ccs,ami
+span=4,4,3,ccs,ami
+span=5,5,3,ccs,ami
+span=6,6,3,ccs,ami
+span=7,7,3,ccs,ami
+span=8,8,3,ccs,ami
 
 bchan=1,2
 dchan=3

Modified: zaptel/trunk/zaphfc/zaphfc.c
===================================================================
--- zaptel/trunk/zaphfc/zaphfc.c	2007-08-05 11:21:06 UTC (rev 3904)
+++ zaptel/trunk/zaphfc/zaphfc.c	2007-08-05 11:43:22 UTC (rev 3905)
@@ -27,6 +27,10 @@
 #include <zaptel.h>
 #include "zaphfc.h"
 
+#ifdef LINUX26
+#include <linux/moduleparam.h>
+#endif
+
 #if CONFIG_PCI
 
 #define CLKDEL_TE	0x0f	/* CLKDEL in TE mode */
@@ -539,11 +543,7 @@
 }
 
 #ifndef RTAITIMING
-#ifdef LINUX26
-static irqreturn_t hfc_interrupt(int irq, void *dev_id, struct pt_regs *regs) {
-#else
-static void hfc_interrupt(int irq, void *dev_id, struct pt_regs *regs) {
-#endif
+ZAP_IRQ_HANDLER(hfc_interrupt) {
     struct hfc_card *hfctmp = dev_id;
     unsigned long flags = 0;
     unsigned char stat;

Modified: zaptel/trunk/ztgsm/ztgsm.c
===================================================================
--- zaptel/trunk/ztgsm/ztgsm.c	2007-08-05 11:21:06 UTC (rev 3904)
+++ zaptel/trunk/ztgsm/ztgsm.c	2007-08-05 11:43:22 UTC (rev 3905)
@@ -25,6 +25,7 @@
 
 static int debug=0;
 static int pcm_xbar=0;
+static int sim = 0;
 static struct ztgsm_card *ztgsm_dev_list = NULL;
 static int ztgsm_dev_count = 0;
 static int ztgsm_spans = 0;
@@ -39,130 +40,76 @@
 }
 
 void ztgsm_switch_on(struct ztgsm_card *gsmtmp, int span) {
-    unsigned int dtr_on_off = 0;
-    unsigned int rts_o = 0;
     unsigned long flags;
     
     printk(KERN_INFO "ztgsm: Powering up span %d ...", span);
     spin_lock_irqsave(&(gsmtmp->lock),flags);
 	gsmtmp->gsmspan[span].led = 0xC1;
-	dtr_on_off = ztgsm_indw_io(gsmtmp, ztgsm_SER_DTR_ON_OFF);
-	dtr_on_off |= (1 << span) | (1 << (span+4));
-	ztgsm_outdw_io(gsmtmp, ztgsm_SER_DTR_ON_OFF, dtr_on_off);
-    
-	rts_o = ztgsm_indw_io(gsmtmp, ztgsm_SER_RTS_O);
-	rts_o |= (1 << span);
-	ztgsm_outdw_io(gsmtmp, ztgsm_SER_RTS_O, rts_o);
+	gsmtmp->dtr_on_off &= ~ (1 << span);
+	ztgsm_outdw_io(gsmtmp, ztgsm_SER_DTR_ON_OFF, gsmtmp->dtr_on_off);
     spin_unlock_irqrestore(&(gsmtmp->lock),flags);
 
     set_current_state(TASK_UNINTERRUPTIBLE);
     schedule_timeout((1000 * HZ) / 1000);
 
     spin_lock_irqsave(&(gsmtmp->lock),flags);
-	dtr_on_off = ztgsm_indw_io(gsmtmp, ztgsm_SER_DTR_ON_OFF);
-        dtr_on_off &= ~(1 << span);
-        dtr_on_off |= 1 << (span+4);
-	ztgsm_outdw_io(gsmtmp, ztgsm_SER_DTR_ON_OFF, dtr_on_off);
-    spin_unlock_irqrestore(&(gsmtmp->lock),flags);
+        gsmtmp->dtr_on_off |= 1 << span;
+	ztgsm_outdw_io(gsmtmp, ztgsm_SER_DTR_ON_OFF, gsmtmp->dtr_on_off);
 
-    set_current_state(TASK_UNINTERRUPTIBLE);
-    schedule_timeout((800 * HZ) / 1000);
-
-    spin_lock_irqsave(&(gsmtmp->lock),flags);
-	dtr_on_off = ztgsm_indw_io(gsmtmp, ztgsm_SER_DTR_ON_OFF);
-	dtr_on_off |= (1 << span) | (1 << (span+4));
-        ztgsm_outdw_io(gsmtmp, ztgsm_SER_DTR_ON_OFF, dtr_on_off);
-    spin_unlock_irqrestore(&(gsmtmp->lock),flags);
-
-    set_current_state(TASK_UNINTERRUPTIBLE);
-    schedule_timeout((8000 * HZ) / 1000);
-
-    spin_lock_irqsave(&(gsmtmp->lock),flags);
-	dtr_on_off = ztgsm_indw_io(gsmtmp, ztgsm_SER_DTR_ON_OFF);
-	dtr_on_off &= ~(1 << (span+4));
-        dtr_on_off |= (1 << span);
-	ztgsm_outdw_io(gsmtmp, ztgsm_SER_DTR_ON_OFF, dtr_on_off);
-
-        rts_o = ztgsm_indw_io(gsmtmp, ztgsm_SER_RTS_O);
-	rts_o &= ~(1 << span);
-        ztgsm_outdw_io(gsmtmp, ztgsm_SER_RTS_O, 0x0);
 	gsmtmp->power[span] = 1;
 	gsmtmp->gsmspan[span].led = 0x81;
     spin_unlock_irqrestore(&(gsmtmp->lock),flags);
 
     printk(" done.\n");
+    gsmtmp->gsmspan[span].span.alarms = ZT_ALARM_NONE;
+    zt_alarm_notify(&gsmtmp->gsmspan[span].span);
 }
 
 void ztgsm_switch_off(struct ztgsm_card *gsmtmp, int span) {
-    unsigned int dtr_on_off = 0;
     unsigned long flags;
+    gsmtmp->gsmspan[span].span.alarms = ZT_ALARM_RED;
+    zt_alarm_notify(&gsmtmp->gsmspan[span].span);
 
     spin_lock_irqsave(&(gsmtmp->lock),flags);
 	gsmtmp->gsmspan[span].led = 0xC0;
-	dtr_on_off = ztgsm_indw_io(gsmtmp, ztgsm_SER_DTR_ON_OFF);
-	printk(KERN_INFO "ztgsm: Powering down span %d (SER_DTR_ON_OFF %x)...", span, dtr_on_off);
+	printk(KERN_INFO "ztgsm: Powering down span %d (SER_DTR_ON_OFF %x)...", span, gsmtmp->dtr_on_off);
     
-	dtr_on_off &= ~ (1 << span);
-	ztgsm_outdw_io(gsmtmp, ztgsm_SER_DTR_ON_OFF, dtr_on_off);
+	gsmtmp->dtr_on_off &= ~ (1 << span);
+	ztgsm_outdw_io(gsmtmp, ztgsm_SER_DTR_ON_OFF, gsmtmp->dtr_on_off);
     spin_unlock_irqrestore(&(gsmtmp->lock),flags);
 
     set_current_state(TASK_UNINTERRUPTIBLE);
-    schedule_timeout((5000 * HZ) / 1000);
+    schedule_timeout((2500 * HZ) / 1000);
 
     spin_lock_irqsave(&(gsmtmp->lock),flags);
-	dtr_on_off = ztgsm_indw_io(gsmtmp, ztgsm_SER_DTR_ON_OFF);
-        dtr_on_off |= (1 << span);
-	ztgsm_outdw_io(gsmtmp, ztgsm_SER_DTR_ON_OFF, dtr_on_off);
+        gsmtmp->dtr_on_off |= (1 << span);
+	ztgsm_outdw_io(gsmtmp, ztgsm_SER_DTR_ON_OFF, gsmtmp->dtr_on_off);
 	gsmtmp->power[span] = 0;
 	gsmtmp->gsmspan[span].led = 0x80;
     spin_unlock_irqrestore(&(gsmtmp->lock),flags);
     printk(" done.\n");
 }
 
-void ztgsm_switch_on_all(struct ztgsm_card *gsmtmp) {
+void ztgsm_switch_on_all(struct ztgsm_card *gsmtmp, int verbose) {
     unsigned long flags;
-    printk(KERN_INFO "ztgsm: Powering up all spans...");
+    if (verbose)
+	printk(KERN_INFO "ztgsm: Powering up all spans...");
     spin_lock_irqsave(&(gsmtmp->lock),flags);
 	gsmtmp->gsmspan[0].led = 0xC1;
         gsmtmp->gsmspan[1].led = 0xC1;
 	gsmtmp->gsmspan[2].led = 0xC1;
         gsmtmp->gsmspan[3].led = 0xC1;
 
-	ztgsm_outdw_io(gsmtmp, ztgsm_SER_DTR_ON_OFF, 0xff);
-    
-	ztgsm_outdw_io(gsmtmp, ztgsm_SER_RTS_O, 0x0f);
+	ztgsm_outdw_io(gsmtmp, ztgsm_SER_DTR_ON_OFF, 0xf0);
     spin_unlock_irqrestore(&(gsmtmp->lock),flags);
 
     set_current_state(TASK_UNINTERRUPTIBLE);
     schedule_timeout((1000 * HZ) / 1000);
 
     spin_lock_irqsave(&(gsmtmp->lock),flags);
-	ztgsm_outdw_io(gsmtmp, ztgsm_SER_DTR_ON_OFF, 0xf0);
-    spin_unlock_irqrestore(&(gsmtmp->lock),flags);
-
-    set_current_state(TASK_UNINTERRUPTIBLE);
-    schedule_timeout((800 * HZ) / 1000);
-
-    spin_lock_irqsave(&(gsmtmp->lock),flags);
 	ztgsm_outdw_io(gsmtmp, ztgsm_SER_DTR_ON_OFF, 0xff);
-    spin_unlock_irqrestore(&(gsmtmp->lock),flags);
-
-    set_current_state(TASK_UNINTERRUPTIBLE);
-    schedule_timeout((8000 * HZ) / 1000);
-
-    spin_lock_irqsave(&(gsmtmp->lock),flags);
-	ztgsm_outdw_io(gsmtmp, ztgsm_SER_DTR_ON_OFF, 0xff);
 	ztgsm_outdw_io(gsmtmp, ztgsm_SER_RTS_O, 0x0); /* 1 == -12 v */
-    
-/* new
-    ztgsm_outdw_io(gsmtmp, ztgsm_SER_DTR_ON_OFF, 0x00);
 
-    set_current_state(TASK_UNINTERRUPTIBLE);
-    schedule_timeout((1000 * HZ) / 1000);
-
-    ztgsm_outdw_io(gsmtmp, ztgsm_SER_DTR_ON_OFF, 0x0f);
-*/    
-
 	gsmtmp->power[0] = 1;
 	gsmtmp->power[1] = 1;
         gsmtmp->power[2] = 1;
@@ -174,29 +121,30 @@
 	gsmtmp->gsmspan[3].led = 0x81;
     spin_unlock_irqrestore(&(gsmtmp->lock),flags);
 
-    printk(" done.\n");
+    if (verbose)
+	printk(" done.\n");
 }
 
-void ztgsm_switch_off_all(struct ztgsm_card *gsmtmp) {
+void ztgsm_switch_off_all(struct ztgsm_card *gsmtmp, int verbose) {
     unsigned long flags;
 
     if (gsmtmp->power[0] || gsmtmp->power[1] || gsmtmp->power[2] || gsmtmp->power[3]) { 
+    if (verbose)
+        printk(KERN_INFO "ztgsm: Powering down all spans...");
     spin_lock_irqsave(&(gsmtmp->lock),flags);
 	gsmtmp->gsmspan[0].led = 0xC0;
         gsmtmp->gsmspan[1].led = 0xC0;
 	gsmtmp->gsmspan[2].led = 0xC0;
         gsmtmp->gsmspan[3].led = 0xC0;
 	
-	printk(KERN_INFO "ztgsm: Powering down all spans...");
 	ztgsm_outdw_io(gsmtmp, ztgsm_SER_DTR_ON_OFF, 0x0);
     spin_unlock_irqrestore(&(gsmtmp->lock),flags);
 
 	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((5000 * HZ) / 1000);
+	schedule_timeout((2500 * HZ) / 1000);
 
     spin_lock_irqsave(&(gsmtmp->lock),flags);
-	ztgsm_outdw_io(gsmtmp, ztgsm_SER_DTR_ON_OFF, 0xf);
-	printk(" done.\n");
+	ztgsm_outdw_io(gsmtmp, ztgsm_SER_DTR_ON_OFF, 0x0f);
 
 	gsmtmp->power[0] = 0;
 	gsmtmp->power[1] = 0;
@@ -208,6 +156,8 @@
         gsmtmp->gsmspan[2].led = 0x80;
 	gsmtmp->gsmspan[3].led = 0x80;
     spin_unlock_irqrestore(&(gsmtmp->lock),flags);
+    if (verbose)
+        printk(" done.\n");
     }
 }
 
@@ -216,58 +166,47 @@
     unsigned long flags;
     struct ztgsm_span *gsmspan = NULL;
     int i = 0;
+    unsigned long ioport;
+    unsigned long pci_io_phys;
+    unsigned long iomem_size;
+    void *pci_io;
+
     if (gsmtmp == NULL) {
 	printk(KERN_INFO "ztgsm: shutting down NULL card!\n");
 	return;
     }
+    ztgsm_switch_off_all(gsmtmp, 1);
 
-    ztgsm_switch_off_all(gsmtmp);
-
     spin_lock_irqsave(&gsmtmp->lock,flags);
 
-    gsmtmp->dead = 1;
+	ztgsm_outdw_io(gsmtmp, ztgsm_SER_TX_EN, 0x0);
+	ztgsm_outdw_io(gsmtmp, ztgsm_SER_RX_EN, 0x0);
 
-    if ((!gsmtmp->pci_io) || (gsmtmp->ioport == 0)) {
-	return;
-    }
-    ztgsm_outdw_io(gsmtmp, ztgsm_SER_INT_MASK, 0x0);
-    ztgsm_outdw_io(gsmtmp, ztgsm_PCM_FC_TOG_BIT, 0x0);
-    ztgsm_outdw_io(gsmtmp, ztgsm_PCM_SAP_EN, 0x0);
+	gsmtmp->dead = 1;
 
+        if ((!gsmtmp->pci_io) || (gsmtmp->ioport == 0)) {
+	    return;
+	}
+	ztgsm_outdw_io(gsmtmp, ztgsm_SER_INT_MASK, 0x0);
+	ztgsm_outdw_io(gsmtmp, ztgsm_PCM_FC_TOG_BIT, 0x0);
+	ztgsm_outdw_io(gsmtmp, ztgsm_PCM_SAP_EN, 0x0);
 
-/*    for (i=0; i < gsmtmp->gsmspans; i++) {
-	ztgsm_switch_off(gsmtmp, i);
-    }  */
+	ztgsm_outdw_io(gsmtmp, ztgsm_LED_DUAL, 0xFF00);
 
+	ioport = gsmtmp->ioport;
+	pci_io = gsmtmp->pci_io;
+	pci_io_phys = gsmtmp->pci_io_phys;
+        iomem_size = gsmtmp->iomem_size;
 
-    ztgsm_outdw_io(gsmtmp, ztgsm_LED_DUAL, 0xFF00);
+	gsmtmp->pci_io = 0;
+	gsmtmp->ioport = 0;
 
-
-    // softreset
-
-    release_region(gsmtmp->ioport, 0x100);
-    iounmap((void *) gsmtmp->pci_io);
-    release_mem_region(gsmtmp->pci_io_phys, gsmtmp->iomem_size);
-
-    gsmtmp->pci_io = 0;
-    gsmtmp->ioport = 0;
-
-    // turn off irqs
-
-    free_irq(gsmtmp->irq,gsmtmp);
-
-    pci_write_config_word(gsmtmp->pcidev, PCI_COMMAND, 0);	
-
-    if (gsmtmp->pcidev != NULL) {
-        pci_disable_device(gsmtmp->pcidev);
-    }
-    
     spin_unlock_irqrestore(&gsmtmp->lock,flags);
 
+
     for (i=0; i < gsmtmp->gsmspans; i++) {
 	gsmspan = &gsmtmp->gsmspan[i];
         if(gsmspan->span.flags & ZT_FLAG_RUNNING) {
-//	    ztgsm_shutdown(&gsmspan->span);
 	    if (debug)
 	        printk(KERN_INFO "ztgsm: shutdown card %d span %d.\n",gsmtmp->cardno,i);
 	}
@@ -278,6 +217,23 @@
 	}
     }
 
+
+    release_region(ioport, 0x100);
+    iounmap((void *) pci_io);
+    release_mem_region(pci_io_phys, iomem_size);
+
+
+    spin_lock_irqsave(&gsmtmp->lock,flags);
+
+	free_irq(gsmtmp->irq,gsmtmp);
+
+	pci_write_config_word(gsmtmp->pcidev, PCI_COMMAND, 0);	
+
+	if (gsmtmp->pcidev != NULL) {
+    	    pci_disable_device(gsmtmp->pcidev);
+	}
+
+    spin_unlock_irqrestore(&gsmtmp->lock,flags);
 }
 
 void ztgsm_register_card(struct ztgsm_card *gsmtmp) {
@@ -326,7 +282,11 @@
     ztgsm_outdw_io(gsmtmp, ztgsm_PCM_FC_TOG_BIT, 0x03);
     ztgsm_outdw_io(gsmtmp, ztgsm_SER_INT_MASK, 0x1FFFF);
     ztgsm_outdw_io(gsmtmp, ztgsm_SER_RX_WATERMARK, 0x0A);
-    ztgsm_outdw_io(gsmtmp, ztgsm_SIM_SEL, 0x0);
+    if (sim) {
+	ztgsm_outdw_io(gsmtmp, ztgsm_SIM_SEL, sim);
+    } else {
+	ztgsm_outdw_io(gsmtmp, ztgsm_SIM_SEL, 0x0);
+    }
     ztgsm_outdw_io(gsmtmp, ztgsm_PCM_SAP_EN, 0x0);
     ztgsm_outdw_io(gsmtmp, ztgsm_PCM_MASK_LAST, 0x001F0000 | 0x1F); /* PCM32 0x100 frames */
 //    ztgsm_outdw_io(gsmtmp, ztgsm_PCM_MASK_LAST, (0x001FC000 | 0x1F)); /* PCM32 0x40 frames */
@@ -363,6 +323,7 @@
     ztgsm_outdw_io(gsmtmp, ztgsm_SER_TX_EN, 0x0F);
     if (debug)
 	printk(KERN_INFO "ztgsm: SER_TX_EN %d SER_RX_EN %d \n", ztgsm_indw_io(gsmtmp, ztgsm_SER_TX_EN), ztgsm_indw_io(gsmtmp, ztgsm_SER_RX_EN));
+    gsmtmp->jitter_offset = 0;
     spin_unlock_irqrestore(&(gsmtmp->lock),flags);
 }
 
@@ -533,6 +494,10 @@
 	    tx_wm_sen = (ztgsm_indw_io(gsmtmp, ztgsm_SER_TX_WM_SEN) & 0xF) | (1 << span);
 	    ztgsm_outdw_io(gsmtmp, ztgsm_SER_TX_WM_SEN, tx_wm_sen);
 //	    printk(KERN_INFO "ztgsm: span %d TX_IDX %d count %d tx_wm_send %d\n", span, gsmtmp->ser_tx_idx[span], count, tx_wm_sen);
+	} else {
+	    if (debug) {
+		printk(KERN_INFO "ztgsm: span %d wanted to TX %d bytes but only %d bytes free fifo space\n", span, gsmtmp->ser_tx_idx[span], left);
+	    }
 	}
     }
     return i;
@@ -599,7 +564,7 @@
 //    slot = span;
     gsmspan = &gsmtmp->gsmspan[span];
     if (gsmspan) {
-	framecnt = gsmtmp->framecnt;
+	framecnt = gsmtmp->framecnt - gsmtmp->jitter_offset;
 	pcmframecnt = framecnt;
     	framecnt &= ztgsm_FRAMES - 1;
 	start = framecnt - 16;
@@ -613,7 +578,7 @@
 	}
 
 	if (fraddr & 3) {
-	    if (debug > 0)
+	    if (debug > 1)
 	        printk(KERN_INFO "ztgsm: RX span %d unaligned word address %#x (fraddr & 3 = %d)\n", span, fraddr, (fraddr & 3));
 	    fraddr -= fraddr & 3; /* align */
 	} 
@@ -632,7 +597,8 @@
 	    *((unsigned int *)&gsmtmp->rxbuf[span][4]) = data;
 //    ztgsm_outdw_io(gsmtmp, ztgsm_LED_DUAL, 0xf);
 	} else {
-	    printk(KERN_INFO "ztgsm: dropped audio span %d fraddr %d addr %d\n", span, fraddr, addr);
+	    if (debug > 2)
+		printk(KERN_INFO "ztgsm: dropped audio span %d fraddr %d addr %d\n", span, fraddr, addr);
 	}
 if (!(gsmtmp->ticks % 1000) && (debug > 4)) {
 	printk(KERN_INFO "ztgsm: RX DATA:");
@@ -673,9 +639,9 @@
 
     gsmspan = &gsmtmp->gsmspan[span];
     if (gsmspan) {
-	framecnt = gsmtmp->framecnt;
+	framecnt = gsmtmp->framecnt - gsmtmp->jitter_offset;
     	framecnt &= ztgsm_FRAMES - 1;
-	start = framecnt + 16;
+	start = framecnt + ztgsm_MAX_FC_DIFF + ztgsm_FRAME_SIZE;
 
 	if (start < 0x0) {
 	    len = -start;
@@ -685,11 +651,13 @@
 	    len = ZT_CHUNKSIZE;
 	    fraddr = start;
 	}
-	fraddr -= fraddr & 3; /* align */
 
 	if (fraddr & 3) {
-//	    printk(KERN_EMERG "ztgsm: unaligned word address %#x\n", addr);
-	} else if (len == ZT_CHUNKSIZE) {
+	    if (debug > 2)
+		printk(KERN_INFO "ztgsm: span_tx unaligned word address %#x\n", fraddr);
+	    fraddr -= fraddr & 3; /* align */
+	}
+	if (len == ZT_CHUNKSIZE) {
 	    addr =(slot << 8 ) | fraddr;
 //	    addr =( (span+1) << 8 ) | fraddr;
 	    ztgsm_outdw(gsmtmp, addr, *((unsigned int*)&(gsmtmp->txbuf[span][0])));
@@ -726,14 +694,11 @@
 static inline void ztgsm_run(struct ztgsm_card *gsmtmp) {
     int s=0;
     struct ztgsm_span *gsmspan = NULL;
+
+
     for (s=0;s<gsmtmp->gsmspans;s++) {
         gsmspan = &gsmtmp->gsmspan[s];
         if (gsmspan) {
-	    if (!(gsmtmp->ticks % 1000)) {
-	        gsmtmp->ticks = 0;
-    	    }
-	    if (gsmtmp->ticks % 300 == 0)
-	        ztgsm_leds(gsmtmp, gsmtmp->ticks);
 	    if (gsmspan->span.flags & ZT_FLAG_RUNNING) {
 		/* oh zaptel! tell us what to transmit... */
     		zt_transmit(&gsmspan->span);
@@ -755,18 +720,15 @@
 
 
 
-#ifdef LINUX26
-static irqreturn_t ztgsm_interrupt(int irq, void *dev_id, struct pt_regs *regs) {
-#else
-static void ztgsm_interrupt(int irq, void *dev_id, struct pt_regs *regs) {
-#endif
+ZAP_IRQ_HANDLER(ztgsm_interrupt) {
     struct ztgsm_card *gsmtmp = dev_id;
     unsigned int ser_status = 0;
     unsigned char mods = 0;
     int s = 0;
     int rx_count = 0;
     unsigned long flags;
-
+    signed int jitter = 0;
+    
     if (!gsmtmp || gsmtmp->dead) {
 #ifdef LINUX26
 		return IRQ_NONE;
@@ -791,21 +753,33 @@
     ser_status = ztgsm_indw_io(gsmtmp, ztgsm_SER_STATUS);
     if (ser_status) {
 	if (ser_status & 0x10000) {
-	    if (gsmtmp->framecnt - gsmtmp->last_framecnt != 8) {
-//		printk(KERN_INFO "ztgsm: missed IRQ, framecnt %d last_framecnt %d (diff %d)\n", gsmtmp->framecnt, gsmtmp->last_framecnt, (gsmtmp->framecnt - gsmtmp->last_framecnt));
-	    }
 	    gsmtmp->ticks++;
-	    if (!(gsmtmp->ticks % 1000)) {
-//		printk(KERN_INFO "ztgsm: pcm framce counter  %d\n", ztgsm_indw_io(gsmtmp, ztgsm_PCM_FRAME_CNT) & 0x1f);
-	    }
-	    if (!(gsmtmp->ticks % 300)) {
-		for (s=0; s<gsmtmp->gsmspans; s++) {
-		    rx_count = ztgsm_ser_rx(gsmtmp, s);
-		    if (debug && rx_count) 
-			printk(KERN_INFO "ztgsm: RX %d bytes on span %d\n", rx_count, s);
+	    jitter = gsmtmp->framecnt - gsmtmp->last_framecnt - ztgsm_FRAME_SIZE;
+	    if (abs(gsmtmp->jitter_offset + jitter) > ztgsm_MAX_FC_DIFF) {
+		if (debug > 1)
+		    printk(KERN_INFO "ztgsm: missed IRQ, framecnt %d last_framecnt %d (diff %d)\n", gsmtmp->framecnt, gsmtmp->last_framecnt, (gsmtmp->framecnt - gsmtmp->last_framecnt));
+		gsmtmp->jitter_offset = 0;
+	    } else {
+		if (gsmtmp->jitter_offset > 0) {
+		    gsmtmp->jitter_offset += jitter;
 		}
+		if ((debug > 1) && gsmtmp->jitter_offset)
+		    printk(KERN_INFO "ztgsm: lagged IRQ, framecnt %d last_framecnt %d (offset %d)\n", gsmtmp->framecnt, gsmtmp->last_framecnt, gsmtmp->jitter_offset);
 	    }
-	    ztgsm_run(gsmtmp);
+	    if (gsmtmp->jitter_offset >= 0) {
+		ztgsm_run(gsmtmp);
+	    }
+
+    	    for (s=0; s<gsmtmp->gsmspans; s++) {
+	        rx_count = ztgsm_ser_rx(gsmtmp, s);
+	    }
+	    if (!(gsmtmp->ticks % 300))
+	        ztgsm_leds(gsmtmp, gsmtmp->ticks);
+	    if (!(gsmtmp->ticks % 1000)) {
+		if (debug > 2)
+		    printk(KERN_INFO "ztgsm: TICK\n");
+	        gsmtmp->ticks = 0;
+    	    }
 	} else if (ser_status & 0x0F) {
 	    mods = (ser_status & 0x0F);
 	    for (s=0; s<gsmtmp->gsmspans; s++) {
@@ -823,7 +797,7 @@
 		if (mods & (1 << s)) {
 		    rx_count = ztgsm_ser_rx(gsmtmp, s);
 		    if (debug) 
-			printk(KERN_INFO "ztgsm: RX %d bytes on span %d\n", rx_count, s);
+			printk(KERN_INFO "ztgsm: RX %d bytes on span %d.\n", rx_count, s);
 		}
 	    }
 	} else if (ser_status & 0xF00) {
@@ -900,16 +874,15 @@
     }
     
     running = span->flags & ZT_FLAG_RUNNING;
-    span->chans[1].flags &= ~ZT_FLAG_HDLC;
-    span->chans[1].flags |= ZT_FLAG_BRIDCHAN;
 
     if (!running) {
+	span->chans[1].flags &= ~ZT_FLAG_HDLC;
+	span->chans[1].flags |= ZT_FLAG_BRIDCHAN;
 	if (!gsmtmp->power[span->offset]) 
 	    ztgsm_switch_on(gsmtmp, span->offset);
 	span->flags |= ZT_FLAG_RUNNING;
-
     } else {
-	printk(KERN_CRIT "already running\n");
+	printk(KERN_INFO "ztgsm: already running\n");
 	return 0;
     }
     return 0;
@@ -926,9 +899,10 @@
     running = span->flags & ZT_FLAG_RUNNING;
 
     if (running) {
-	span->flags |= ZT_FLAG_RUNNING;
-	if (gsmtmp->power[span->offset]) 
+	span->flags &= ~ZT_FLAG_RUNNING;
+	if (gsmtmp->power[span->offset]) {
 	    ztgsm_switch_off(gsmtmp, span->offset);
+	}
     }
     return 0;
 }
@@ -1139,6 +1113,7 @@
 	}
         ztgsm_leds(gsmtmp, 0);
 
+	gsmtmp->dtr_on_off = 0x0f;
 
 	gsmtmp->version = ztgsm_indw_io(gsmtmp, ztgsm_VERS_A);
 	printk(KERN_INFO "ztgsm: VERSION %x\n", gsmtmp->version);
@@ -1151,7 +1126,20 @@
 	ztgsm_register_card(gsmtmp);
 
 	ztgsm_startCard(gsmtmp);
-	ztgsm_switch_on_all(gsmtmp);
+
+	if (sim >= 0x10) {
+	    printk(KERN_INFO "ztgsm: Invalid value for parameter sim.\n");
+	    sim = 0;
+	}
+
+	if (sim) {
+	    ztgsm_switch_off_all(gsmtmp, 0);
+	    printk(KERN_INFO "ztgsm: Initializing SIM extensions...");
+	    ztgsm_switch_on_all(gsmtmp, 0);
+	    printk("done\n");
+	} else {
+	    ztgsm_switch_on_all(gsmtmp, 1);
+	}
 	
 	tmp = pci_find_device(PCI_VENDOR_ID_CCD,pcidid,multi_gsm);
     }
@@ -1193,9 +1181,11 @@
 #ifdef LINUX26
 module_param(debug, int, 0600);
 module_param(pcm_xbar, int, 0600);
+module_param(sim, int, 0600);
 #else
 MODULE_PARM(debug,"i");
 MODULE_PARM(pcm_xbar,"i");
+MODULE_PARM(sim,"i");
 #endif
 
 MODULE_DESCRIPTION("uno/duao/quad GSM zaptel driver");

Modified: zaptel/trunk/ztgsm/ztgsm.h
===================================================================
--- zaptel/trunk/ztgsm/ztgsm.h	2007-08-05 11:21:06 UTC (rev 3904)
+++ zaptel/trunk/ztgsm/ztgsm.h	2007-08-05 11:43:22 UTC (rev 3905)
@@ -3,6 +3,8 @@
 #define ztgsm_SPANS	4
 #define ztgsm_SER_BUF_SIZE	1000
 #define ztgsm_FRAMES	0x100
+#define ztgsm_MAX_FC_DIFF 32
+#define ztgsm_FRAME_SIZE ZT_CHUNKSIZE
 
 typedef struct ztgsm_span {
     int led;	/* 0 == RED 1 == GREEN  0x80 == on 0x40 == blink */
@@ -20,6 +22,7 @@
 typedef struct ztgsm_card {
     spinlock_t lock;
     unsigned char power[ztgsm_SPANS];
+    unsigned int dtr_on_off;
     int cardID;
     int dead;
     unsigned char cardno;
@@ -28,6 +31,7 @@
     void *pci_io;
     unsigned int framecnt;
     unsigned int last_framecnt;
+    signed int jitter_offset;
     unsigned long pci_io_phys;
     unsigned int version;
 //    unsigned char *pci_io;




More information about the Pkg-voip-commits mailing list