[Pkg-voip-commits] r3906 - in zaptel/trunk/debian: . patches

paravoid at alioth.debian.org paravoid at alioth.debian.org
Sun Aug 5 11:56:09 UTC 2007


Author: paravoid
Date: 2007-08-05 11:56:09 +0000 (Sun, 05 Aug 2007)
New Revision: 3906

Added:
   zaptel/trunk/debian/patches/zaphfc-florz.dpatch
Modified:
   zaptel/trunk/debian/changelog
   zaptel/trunk/debian/control
   zaptel/trunk/debian/copyright
   zaptel/trunk/debian/patches/00list
Log:
* Add florz' patch to zaphfc; removes RTAI support.

Modified: zaptel/trunk/debian/changelog
===================================================================
--- zaptel/trunk/debian/changelog	2007-08-05 11:43:22 UTC (rev 3905)
+++ zaptel/trunk/debian/changelog	2007-08-05 11:56:09 UTC (rev 3906)
@@ -14,8 +14,9 @@
   * bristuff 0.4.0-test4 
     - Add zaptel.patch as debian/patches/bristuff.dpatch.
     - Update zaphfc, qozap, cwain and ztgsm.
+  * Add florz' patch to zaphfc; removes RTAI support.
 
- -- Faidon Liambotis <paravoid at debian.org>  Sun, 05 Aug 2007 14:41:53 +0300
+ -- Faidon Liambotis <paravoid at debian.org>  Sun, 05 Aug 2007 14:55:36 +0300
 
 zaptel (1:1.4.4~dfsg-1) unstable; urgency=low
 

Modified: zaptel/trunk/debian/control
===================================================================
--- zaptel/trunk/debian/control	2007-08-05 11:43:22 UTC (rev 3905)
+++ zaptel/trunk/debian/control	2007-08-05 11:56:09 UTC (rev 3906)
@@ -42,7 +42,6 @@
 Architecture: all
 Depends: debhelper (>> 4.0), module-assistant (>= 0.8.1), bzip2
 Recommends: zaptel
-Suggests: rtai-source
 Description: Zapata telephony interface (source code for kernel driver)
  This package contains the source code for zaptel kernel module providing
  device drivers for various telephony hardware, including the Wildcard 

Modified: zaptel/trunk/debian/copyright
===================================================================
--- zaptel/trunk/debian/copyright	2007-08-05 11:43:22 UTC (rev 3905)
+++ zaptel/trunk/debian/copyright	2007-08-05 11:56:09 UTC (rev 3906)
@@ -1,7 +1,12 @@
 This package was debianized by Matt Zimmerman <mdz at debian.org> on
 Mon, 17 Jun 2002 10:31:21 -0400.
 
-It was downloaded from http://www.asterisk.org/
+It was downloaded from
+  http://www.asterisk.org/
+bristuff patch was downloaded from
+  http://www.junghanns.net/download/
+florz' patch for the zaphfc driver was downloaded from
+  http://zaphfc.florz.dyndns.org/
 
 Upstream source has been modified to comply with the Debian Free 
 Software Guildlines (DFSG), by the removal of the firmware files:
@@ -42,9 +47,12 @@
 ztd-loc.c: * Copyright (C) 2004, Axialys Interactive
 ztdummy.c: * Copyright (C) 2002, Hermes Softlab
 
-bristuff driver:
- * Copyright (C) 2002, 2003, 2004, Junghanns.NET GmbH
+debian/patches/bristuff.dpatch, zaphfc, qozap, cwain, ztgsm:
+ * Copyright (C) 2002, 2003, 2004, 2005 Junghanns.NET GmbH
 
+debian/patches/zaphfc-florz.dpatch:
+ * Copyright (C) 2004, 2005, 2006  Florian Zumbiehl <florz at gmx.de>
+
 vzaphfc is derived from bristuff and since enhanced by:
  * Copyright (C) 2004-2006, Daniele "Vihai" Orlandi <daniele at orlandi.com>
  * Copyright (C) 2006, headissue GmbH; Jens Wilke <jw_vzaphfc at headissue.com>

Modified: zaptel/trunk/debian/patches/00list
===================================================================
--- zaptel/trunk/debian/patches/00list	2007-08-05 11:43:22 UTC (rev 3905)
+++ zaptel/trunk/debian/patches/00list	2007-08-05 11:56:09 UTC (rev 3906)
@@ -3,3 +3,4 @@
 oslec_zaptel
 zaptel_perl
 bristuff
+zaphfc-florz

Added: zaptel/trunk/debian/patches/zaphfc-florz.dpatch
===================================================================
--- zaptel/trunk/debian/patches/zaphfc-florz.dpatch	                        (rev 0)
+++ zaptel/trunk/debian/patches/zaphfc-florz.dpatch	2007-08-05 11:56:09 UTC (rev 3906)
@@ -0,0 +1,1285 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## zaphfc-florz.dpatch by Faidon Liambotis <paravoid at debian.org>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: florz' patch to zaphfc
+## DP: Author: Florian Zumbiehl <florz at gmx.de>
+
+ at DPATCH@
+diff -urNad trunk~/zaphfc/Makefile trunk/zaphfc/Makefile
+--- trunk~/zaphfc/Makefile	2007-07-22 05:01:06.000000000 +0300
++++ trunk/zaphfc/Makefile	2007-08-05 14:46:58.000000000 +0300
+@@ -2,12 +2,11 @@
+ BRISTUFFBASE = $(shell dirname `pwd`)
+ 
+ ZAP = $(shell [ -f $(BRISTUFFBASE)/zaptel/zaptel.h ] && echo "-I$(BRISTUFFBASE)/zaptel")
+-RTAI = $(shell [ -f /usr/realtime/include/rtai.h ] && echo "-DRTAITIMING -I/usr/realtime/include")
+ 
+-CFLAGS+=-I. $(ZAP) $(RTAI) -O2 -g -Wall -DBUILDING_TONEZONE 
++CFLAGS+=-I. $(ZAP) -O2 -g -Wall -DBUILDING_TONEZONE 
+ CFLAGS+=$(shell if uname -m | grep -q ppc; then echo "-fsigned-char"; fi)
+ 
+-KFLAGS=-D__KERNEL__ -DMODULE -DEXPORT_SYMTAB -fomit-frame-pointer -O2 -Wall -I$(KINCLUDES) $(ZAP) $(RTAI) -Wall
++KFLAGS=-D__KERNEL__ -DMODULE -DEXPORT_SYMTAB -fomit-frame-pointer -O2 -Wall -I$(KINCLUDES) $(ZAP) -Wall
+ KFLAGS+=$(shell [ -f $(KINCLUDES)/linux/modversions.h ] && echo "-DMODVERSIONS -include $(KINCLUDES)/linux/modversions.h")
+ KFLAGS+=$(shell if uname -m | grep -q ppc; then echo "-msoft-float -fsigned-char"; fi)
+ 
+diff -urN bristuff-0.4.0-test1/zaphfc/zaphfc.c zaphfc_0.4.0-test1_florz-13/zaphfc.c
+--- bristuff-0.4.0-test1/zaphfc/zaphfc.c	2007-04-03 11:38:45.000000000 +0200
++++ zaphfc_0.4.0-test1_florz-13/zaphfc.c	2007-04-17 21:14:39.000000000 +0200
+@@ -7,19 +7,21 @@
+  *
+  * Klaus-Peter Junghanns <kpj at junghanns.net>
+  *
++ * Copyright (C) 2004, 2005, 2006  Florian Zumbiehl <florz at gmx.de>
++ *  - support for slave mode of the HFC-S chip which allows it to
++ *    sync its sample clock to an external source/another HFC chip
++ *  - support for "interrupt bundling" (let only one card generate
++ *    8 kHz timing interrupt no matter how many cards there are
++ *    in the system)
++ *  - interrupt loss tolerant b channel handling
++ *
+  * This program is free software and may be modified and
+- * distributed under the terms of the GNU Public License.
++ * distributed under the terms of the GNU General Public License.
+  *
+  */
+ 
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+-#ifdef RTAITIMING
+-#include <asm/io.h>
+-#include <rtai.h>
+-#include <rtai_sched.h>
+-#include <rtai_fifos.h>
+-#endif
+ #include <linux/pci.h>
+ #include <linux/init.h>
+ #include <linux/interrupt.h>
+@@ -31,6 +33,8 @@
+ #include <linux/moduleparam.h>
+ #endif
+ 
++#define log2(n) ffz(~(n))
++
+ #if CONFIG_PCI
+ 
+ #define CLKDEL_TE	0x0f	/* CLKDEL in TE mode */
+@@ -73,41 +77,30 @@
+ static int hfc_dev_count = 0;
+ static int modes = 0; // all TE
+ static int debug = 0;
++static int sync_slave = 0; // all master
++static int timer_card = 0;
++static int jitterbuffer = 1;
+ static struct pci_dev *multi_hfc = NULL;
+ static spinlock_t registerlock = SPIN_LOCK_UNLOCKED;
+ 
+-void hfc_shutdownCard(struct hfc_card *hfctmp) {
+-    unsigned long flags;
+-
+-    if (hfctmp == NULL) {
+-	return;
+-    }
+-
+-    if (hfctmp->pci_io == NULL) {
+-	return;
+-    }
+-    
+-    spin_lock_irqsave(&hfctmp->lock,flags);
+-
++void hfc_shutdownCard1(struct hfc_card *hfctmp) {
+     printk(KERN_INFO "zaphfc: shutting down card at %p.\n",hfctmp->pci_io);
+ 
+     /* Clear interrupt mask */
+     hfctmp->regs.int_m2 = 0;
+     hfc_outb(hfctmp, hfc_INT_M2, hfctmp->regs.int_m2);
+ 
+-    /* Reset pending interrupts */
+-    hfc_inb(hfctmp, hfc_INT_S1);
++    /* Remove interrupt handler */
++    free_irq(hfctmp->irq,hfctmp);
++}
++
++void hfc_shutdownCard2(struct hfc_card *hfctmp) {
++    unsigned long flags;
+ 
+-    /* Wait for interrupts that might still be pending */
+-    spin_unlock_irqrestore(&hfctmp->lock, flags);
+-    set_current_state(TASK_UNINTERRUPTIBLE);
+-    schedule_timeout((30 * HZ) / 1000);	// wait 30 ms
+     spin_lock_irqsave(&hfctmp->lock,flags);
+ 
+-    /* Remove interrupt handler */
+-    if (hfctmp->irq) {
+-	free_irq(hfctmp->irq, hfctmp);
+-    }
++    /* Reset pending interrupts */
++    hfc_inb(hfctmp, hfc_INT_S1);
+ 
+     /* Soft-reset the card */
+     hfc_outb(hfctmp, hfc_CIRM, hfc_CIRM_RESET); // softreset on
+@@ -121,8 +114,8 @@
+ 
+     pci_write_config_word(hfctmp->pcidev, PCI_COMMAND, 0);	// disable memio and bustmaster
+ 
+-    if (hfctmp->fifomem != NULL) {
+-        kfree(hfctmp->fifomem);
++    if (hfctmp->fifos != NULL) {
++	free_pages((unsigned long)hfctmp->fifos,log2(hfc_FIFO_MEM_SIZE_PAGES));
+     }
+     iounmap((void *) hfctmp->pci_io);
+     hfctmp->pci_io = NULL;
+@@ -132,11 +125,24 @@
+     spin_unlock_irqrestore(&hfctmp->lock,flags);
+     if (hfctmp->ztdev != NULL) {
+ 	zt_unregister(&hfctmp->ztdev->span);
+-	kfree(hfctmp->ztdev);
++	vfree(hfctmp->ztdev);
+ 	printk(KERN_INFO "unregistered from zaptel.\n");
+     }
+ }
+ 
++void hfc_shutdownCard(struct hfc_card *hfctmp) {
++    if (hfctmp == NULL) {
++	return;
++    }
++
++    if (hfctmp->pci_io == NULL) {
++	return;
++    }
++
++    hfc_shutdownCard1(hfctmp);
++    hfc_shutdownCard2(hfctmp);
++}
++
+ void hfc_resetCard(struct hfc_card *hfctmp) {
+     unsigned long flags;
+ 
+@@ -180,14 +186,14 @@
+     hfctmp->regs.ctmt = hfc_CTMT_TRANSB1 | hfc_CTMT_TRANSB2; // all bchans are transparent , no freaking hdlc
+     hfc_outb(hfctmp, hfc_CTMT, hfctmp->regs.ctmt);
+ 
+-    hfctmp->regs.int_m1 = 0;
++    hfctmp->regs.int_m1=hfc_INTS_L1STATE;
++    if(hfctmp->cardno==timer_card){
++	hfctmp->regs.int_m2=hfc_M2_PROC_TRANS;
++    }else{
++	hfctmp->regs.int_m1|=hfc_INTS_DREC;
++	hfctmp->regs.int_m2=0;
++    }
+     hfc_outb(hfctmp, hfc_INT_M1, hfctmp->regs.int_m1);
+-
+-#ifdef RTAITIMING
+-    hfctmp->regs.int_m2 = 0;
+-#else
+-    hfctmp->regs.int_m2 = hfc_M2_PROC_TRANS;
+-#endif
+     hfc_outb(hfctmp, hfc_INT_M2, hfctmp->regs.int_m2);
+ 
+     /* Clear already pending ints */
+@@ -199,8 +205,8 @@
+ 	hfctmp->regs.sctrl = 3 | hfc_SCTRL_NONE_CAP | hfc_SCTRL_MODE_TE;	/* set tx_lo mode, error in datasheet ! */
+     }
+ 
+-    hfctmp->regs.mst_mode = hfc_MST_MODE_MASTER;	/* HFC Master Mode */
+     hfc_outb(hfctmp, hfc_MST_MODE, hfctmp->regs.mst_mode);
++    hfc_outb(hfctmp, hfc_MST_EMOD, hfctmp->regs.mst_emod);
+ 
+     hfc_outb(hfctmp, hfc_SCTRL, hfctmp->regs.sctrl);
+     hfctmp->regs.sctrl_r = 3;
+@@ -212,10 +218,8 @@
+     hfc_outb(hfctmp, hfc_CIRM, 0x80 | 0x40);	// bit order
+ 
+     /* Finally enable IRQ output */
+-#ifndef RTAITIMING
+     hfctmp->regs.int_m2 |= hfc_M2_IRQ_ENABLE;
+     hfc_outb(hfctmp, hfc_INT_M2, hfctmp->regs.int_m2);
+-#endif
+ 
+     /* clear pending ints */
+     hfc_inb(hfctmp, hfc_INT_S1); 
+@@ -232,370 +236,219 @@
+     spin_unlock(&registerlock);
+ }
+ 
+-static void hfc_btrans(struct hfc_card *hfctmp, char whichB) {
+-    // we are called with irqs disabled from the irq handler
+-    int count, maxlen, total;
+-    unsigned char *f1, *f2;
+-    unsigned short *z1, *z2, newz1;
+-    int freebytes;
+-
+-    if (whichB == 1) {
+-	f1 = (char *)(hfctmp->fifos + hfc_FIFO_B1TX_F1);
+-        f2 = (char *)(hfctmp->fifos + hfc_FIFO_B1TX_F2);
+-	z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B1TX_Z1 + (*f1 * 4));
+-	z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B1TX_Z2 + (*f1 * 4));
+-    } else {
+-	f1 = (char *)(hfctmp->fifos + hfc_FIFO_B2TX_F1);
+-        f2 = (char *)(hfctmp->fifos + hfc_FIFO_B2TX_F2);
+-	z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B2TX_Z1 + (*f1 * 4));
+-	z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B2TX_Z2 + (*f1 * 4));
+-    }
+-
+-    freebytes = *z2 - *z1;
+-    if (freebytes <= 0) {
+-	freebytes += hfc_B_FIFO_SIZE;
+-    }
+-    count = ZT_CHUNKSIZE;
+-
+-    total = count;
+-    if (freebytes < count) {
+-	hfctmp->clicks++;
+-	/* only spit out this warning once per second to not make things worse! */
+-	if (hfctmp->clicks > 100) {
+-	    printk(KERN_CRIT "zaphfc: bchan tx fifo full, dropping audio! (z1=%d, z2=%d)\n",*z1,*z2);
+-	    hfctmp->clicks = 0;
+-	}
+-	return;
+-    }
+-    
+-    maxlen = (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL) - *z1;
+-    if (maxlen > count) {
+-        maxlen = count;
+-    }
+-    newz1 = *z1 + total;
+-    if (newz1 >= (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL)) { newz1 -= hfc_B_FIFO_SIZE; }
++/*===========================================================================*/
+ 
+-	if (whichB == 1) {
+-	    memcpy((char *)(hfctmp->fifos + hfc_FIFO_B1TX_ZOFF + *z1),hfctmp->ztdev->chans[0].writechunk, maxlen);
+-	} else {
+-	    memcpy((char *)(hfctmp->fifos + hfc_FIFO_B2TX_ZOFF + *z1),hfctmp->ztdev->chans[1].writechunk, maxlen);
+-	}
+-	
+-	count -= maxlen;
+-	if (count > 0) {
+-	// Buffer wrap
+-	    if (whichB == 1) {
+-	        memcpy((char *)(hfctmp->fifos + hfc_FIFO_B1TX_ZOFF + hfc_B_SUB_VAL),hfctmp->ztdev->chans[0].writechunk+maxlen, count);
+-	    } else {
+-	        memcpy((char *)(hfctmp->fifos + hfc_FIFO_B2TX_ZOFF + hfc_B_SUB_VAL),hfctmp->ztdev->chans[1].writechunk+maxlen, count);
+-	    }
+-	}
++#if hfc_B_FIFO_SIZE%ZT_CHUNKSIZE
++#error hfc_B_FIFO_SIZE is not a multiple of ZT_CHUNKSIZE even though the code assumes this
++#endif
++    
++static void hfc_dch_init(struct hfc_card *hfctmp){
++    struct dch *chtmp=&hfctmp->dch;
+ 
+-    *z1 = newz1;	/* send it now */
++    chtmp->rx.f1.p=(u8 *)(hfctmp->fifos+hfc_FIFO_DRX_F1);
++    chtmp->rx.f2.v=0x1f;
++    chtmp->rx.f2.z2.v=0x1ff;
+ 
+-//    if (count > 0) printk(KERN_CRIT "zaphfc: bchan tx fifo (f1=%d, f2=%d, z1=%d, z2=%d)\n",(*f1) & hfc_FMASK,(*f2) & hfc_FMASK, *z1, *z2);
+-    return;    
++    chtmp->tx.f1.p=(u8 *)(hfctmp->fifos+hfc_FIFO_DTX_F1);
++    chtmp->tx.f1.v=0x1f;
++    chtmp->tx.f1.z1.v=0x1ff;
++    chtmp->tx.f2.p=(u8 *)(hfctmp->fifos+hfc_FIFO_DTX_F2);
+ }
+ 
+-static void hfc_brec(struct hfc_card *hfctmp, char whichB) {
+-    // we are called with irqs disabled from the irq handler
+-    int count, maxlen, drop;
+-    volatile unsigned char *f1, *f2;
+-    volatile unsigned short *z1, *z2, newz2;
+-    int bytes = 0;
+-
+-    if (whichB == 1) {
+-	f1 = (char *)(hfctmp->fifos + hfc_FIFO_B1RX_F1);
+-        f2 = (char *)(hfctmp->fifos + hfc_FIFO_B1RX_F2);
+-	z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B1RX_Z1 + (*f1 * 4));
+-	z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B1RX_Z2 + (*f1 * 4));
+-    } else {
+-	f1 = (char *)(hfctmp->fifos + hfc_FIFO_B2RX_F1);
+-        f2 = (char *)(hfctmp->fifos + hfc_FIFO_B2RX_F2);
+-	z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B2RX_Z1 + (*f1 * 4));
+-	z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B2RX_Z2 + (*f1 * 4));
+-    }
++static void hfc_bch_init(struct hfc_card *hfctmp){
++    struct bch *chtmp=&hfctmp->bch;
+ 
+-    bytes = *z1 - *z2;
+-    if (bytes < 0) {
+-	bytes += hfc_B_FIFO_SIZE;
+-    }
+-    count = ZT_CHUNKSIZE;
+-    
+-    if (bytes < ZT_CHUNKSIZE) {
+-#ifndef RTAITIMING
+-	printk(KERN_CRIT "zaphfc: bchan rx fifo not enough bytes to receive! (z1=%d, z2=%d, wanted %d got %d), probably a buffer overrun.\n",*z1,*z2,ZT_CHUNKSIZE,bytes);
+-#endif
+-	return;
+-    }
++    chtmp->checkcnt=0;
++    chtmp->fill_fifo=0;
+ 
+-    /* allowing the buffering of hfc_BCHAN_BUFFER bytes of audio data works around irq jitter */
+-    if (bytes > hfc_BCHAN_BUFFER + ZT_CHUNKSIZE) {
+-	/* if the system is too slow to handle it, we will have to drop it all (except 1 zaptel chunk) */
+-	drop = bytes - ZT_CHUNKSIZE;
+-	hfctmp->clicks++;
+-	/* only spit out this warning once per second to not make things worse! */
+-	if (hfctmp->clicks > 100) {
+-	    printk(KERN_CRIT "zaphfc: dropped audio (z1=%d, z2=%d, wanted %d got %d, dropped %d).\n",*z1,*z2,count,bytes,drop);
+-	    hfctmp->clicks = 0;
+-	}
+-	/* hm, we are processing the b chan data tooooo slowly... let's drop the lost audio */
+-	newz2 = *z2 + drop;
+-	if (newz2 >= (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL)) { 
+-	    newz2 -= hfc_B_FIFO_SIZE; 
+-	}
+-	*z2 = newz2;
+-    }
++    chtmp->rx.c[0].z1p=(unsigned short *)(hfctmp->fifos+hfc_FIFO_B1RX_Z1+0x1f*4);
++    chtmp->rx.c[0].fifo_base=(char *)(hfctmp->fifos+hfc_FIFO_B1RX_ZOFF);
++    chtmp->rx.c[1].z1p=(unsigned short *)(hfctmp->fifos+hfc_FIFO_B2RX_Z1+0x1f*4);
++    chtmp->rx.c[1].fifo_base=(char *)(hfctmp->fifos+hfc_FIFO_B2RX_ZOFF);
++    chtmp->rx.z2=hfc_B_SUB_VAL;
++    chtmp->rx.diff=0;
+ 
+-    
+-    maxlen = (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL) - *z2;
+-    if (maxlen > count) {
+-        maxlen = count;
+-    }
+-    if (whichB == 1) {
+-        memcpy(hfctmp->ztdev->chans[0].readchunk,(char *)(hfctmp->fifos + hfc_FIFO_B1RX_ZOFF + *z2), maxlen);
+-    } else {
+-        memcpy(hfctmp->ztdev->chans[1].readchunk,(char *)(hfctmp->fifos + hfc_FIFO_B2RX_ZOFF + *z2), maxlen);
+-    }
+-    newz2 = *z2 + count;
+-    if (newz2 >= (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL)) { 
+-        newz2 -= hfc_B_FIFO_SIZE; 
++    chtmp->tx.c[0].z1p=(unsigned short *)(hfctmp->fifos+hfc_FIFO_B1TX_Z1+0x1f*4);
++    chtmp->tx.c[0].z2p=(unsigned short *)(hfctmp->fifos+hfc_FIFO_B1TX_Z2+0x1f*4);
++    chtmp->tx.c[0].fifo_base=(char *)(hfctmp->fifos+hfc_FIFO_B1TX_ZOFF);
++    chtmp->tx.c[0].filled=0;
++    chtmp->tx.c[1].z1p=(unsigned short *)(hfctmp->fifos+hfc_FIFO_B2TX_Z1+0x1f*4);
++    chtmp->tx.c[1].z2p=(unsigned short *)(hfctmp->fifos+hfc_FIFO_B2TX_Z2+0x1f*4);
++    chtmp->tx.c[1].fifo_base=(char *)(hfctmp->fifos+hfc_FIFO_B2TX_ZOFF);
++    chtmp->tx.c[1].filled=0;
++    chtmp->tx.z1=hfc_B_SUB_VAL;
++    chtmp->tx.diff=0;
++
++    hfc_dch_init(hfctmp);
++
++    chtmp->initialized=0;
++}
++
++static int hfc_bch_check(struct hfc_card *hfctmp){
++    struct bch *chtmp=&hfctmp->bch;
++    int x,r;
++
++    for(x=0;x<2;x++){
++	chtmp->tx.c[x].filled=(chtmp->tx.z1-*chtmp->tx.c[x].z2p+hfc_B_FIFO_SIZE)%hfc_B_FIFO_SIZE;
++	chtmp->rx.c[x].filled=(*chtmp->rx.c[x].z1p-chtmp->rx.z2+hfc_B_FIFO_SIZE)%hfc_B_FIFO_SIZE;
+     }
+-    *z2 = newz2;
+-	
+-    count -= maxlen;
+-    if (count > 0) {
+-    // Buffer wrap
+-        if (whichB == 1) {
+-	    z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B1RX_Z2 + (*f1 * 4));
+-    	    memcpy(hfctmp->ztdev->chans[0].readchunk + maxlen,(char *)(hfctmp->fifos + hfc_FIFO_B1RX_ZOFF + hfc_B_SUB_VAL), count);
+-	} else {
+-	    z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_B2RX_Z2 + (*f1 * 4));
+-	    memcpy(hfctmp->ztdev->chans[1].readchunk + maxlen,(char *)(hfctmp->fifos + hfc_FIFO_B2RX_ZOFF + hfc_B_SUB_VAL), count);
+-	}
+-	newz2 = *z2 + count;
+-	if (newz2 >= (hfc_B_FIFO_SIZE + hfc_B_SUB_VAL)) { 
+-	    newz2 -= hfc_B_FIFO_SIZE; 
++    if(chtmp->fill_fifo){
++	chtmp->checkcnt++;
++	chtmp->checkcnt%=ZT_CHUNKSIZE;
++	r=!chtmp->checkcnt;
++    }else{
++	x=chtmp->tx.c[0].filled-chtmp->tx.c[1].filled;
++	if(abs(x-chtmp->tx.diff)>1){
++	    printk(KERN_CRIT "zaphfc[%d]: tx sync changed: %d, %d\n",hfctmp->cardno,chtmp->tx.c[0].filled,chtmp->tx.c[1].filled);
++	    chtmp->tx.diff=x;
+ 	}
++	r=chtmp->tx.c[0].filled<=ZT_CHUNKSIZE*jitterbuffer&&chtmp->tx.c[1].filled<=ZT_CHUNKSIZE*jitterbuffer;
+     }
++    return(r);
++}
+ 
++#define hfc_bch_inc_z(a,b) (a)=((a)-hfc_B_SUB_VAL+(b))%hfc_B_FIFO_SIZE+hfc_B_SUB_VAL
+ 
+-    if (whichB == 1) {
+-	zt_ec_chunk(&hfctmp->ztdev->chans[0], hfctmp->ztdev->chans[0].readchunk, hfctmp->ztdev->chans[0].writechunk);
+-    } else {
+-	zt_ec_chunk(&hfctmp->ztdev->chans[1], hfctmp->ztdev->chans[1].readchunk, hfctmp->ztdev->chans[1].writechunk);
++static void hfc_bch_tx(struct hfc_card *hfctmp){
++    struct bch *chtmp=&hfctmp->bch;
++    int x;
++
++    for(x=0;x<2;x++)
++	memcpy((void *)(chtmp->tx.c[x].fifo_base+chtmp->tx.z1),hfctmp->ztdev->chans[x].writechunk,ZT_CHUNKSIZE);
++    hfc_bch_inc_z(chtmp->tx.z1,ZT_CHUNKSIZE);
++    if(chtmp->fill_fifo){
++	chtmp->fill_fifo--;
++    }else if(chtmp->tx.c[0].filled<=1||chtmp->tx.c[1].filled<=1){
++	chtmp->fill_fifo=jitterbuffer;
++	if(chtmp->initialized)
++	    printk(KERN_CRIT "zaphfc[%d]: b channel buffer underrun: %d, %d\n",hfctmp->cardno,chtmp->tx.c[0].filled,chtmp->tx.c[1].filled);
+     }
+-    return;    
++    if(!chtmp->fill_fifo)
++	for(x=0;x<2;x++)*chtmp->tx.c[x].z1p=chtmp->tx.z1;
+ }
+ 
+-
+-static void hfc_dtrans(struct hfc_card *hfctmp) {
+-    // we are called with irqs disabled from the irq handler
++static void hfc_bch_rx(struct hfc_card *hfctmp){
++    struct bch *chtmp=&hfctmp->bch;
+     int x;
+-    int count, maxlen, total;
+-    unsigned char *f1, *f2, newf1;
+-    unsigned short *z1, *z2, newz1;
+-    int frames, freebytes;
+ 
+-    if (hfctmp->ztdev->chans[2].bytes2transmit == 0) {
+-	return;
++    x=chtmp->rx.c[0].filled-chtmp->rx.c[1].filled;
++    if(abs(x-chtmp->rx.diff)>1){
++	printk(KERN_CRIT "zaphfc[%d]: rx sync changed: %d, %d\n",hfctmp->cardno,chtmp->rx.c[0].filled,chtmp->rx.c[1].filled);
++	chtmp->rx.diff=x;
+     }
+-
+-    f1 = (char *)(hfctmp->fifos + hfc_FIFO_DTX_F1);
+-    f2 = (char *)(hfctmp->fifos + hfc_FIFO_DTX_F2);
+-    z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DTX_Z1 + (*f1 * 4));
+-    z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DTX_Z2 + (*f1 * 4));
+-
+-    frames = (*f1 - *f2) & hfc_FMASK;
+-    if (frames < 0) {
+-	frames += hfc_MAX_DFRAMES + 1;
++    if(chtmp->rx.c[0].filled>=ZT_CHUNKSIZE&&chtmp->rx.c[1].filled>=ZT_CHUNKSIZE){
++	if((chtmp->rx.c[0].filled>=ZT_CHUNKSIZE*(jitterbuffer+2)&&chtmp->rx.c[1].filled>=ZT_CHUNKSIZE*(jitterbuffer+2))||!chtmp->initialized){
++	    if(chtmp->initialized)
++		printk(KERN_CRIT "zaphfc[%d]: b channel buffer overflow: %d, %d\n",hfctmp->cardno,chtmp->rx.c[0].filled,chtmp->rx.c[1].filled);
++	    hfc_bch_inc_z(chtmp->rx.z2,chtmp->rx.c[0].filled-chtmp->rx.c[0].filled%ZT_CHUNKSIZE-ZT_CHUNKSIZE);
++	    chtmp->initialized=1;
++	}
++	for(x=0;x<2;x++){
++	    memcpy(hfctmp->ztdev->chans[x].readchunk,(void *)(chtmp->rx.c[x].fifo_base+chtmp->rx.z2),ZT_CHUNKSIZE);
++	    zt_ec_chunk(&hfctmp->ztdev->chans[x],hfctmp->ztdev->chans[x].readchunk,hfctmp->ztdev->chans[x].writechunk);
++	}
++	hfc_bch_inc_z(chtmp->rx.z2,ZT_CHUNKSIZE);
+     }
++}
+ 
+-    if (frames >= hfc_MAX_DFRAMES) {
+-	printk(KERN_CRIT "zaphfc: dchan tx fifo total number of frames exceeded!\n");
+-	return;
+-    }
++/*===========================================================================*/
+ 
+-    freebytes = *z2 - *z1;
+-    if (freebytes <= 0) {
+-	freebytes += hfc_D_FIFO_SIZE;
+-    }
+-    count = hfctmp->ztdev->chans[2].bytes2transmit;
+-
+-    total = count;
+-    if (freebytes < count) {
+-	printk(KERN_CRIT "zaphfc: dchan tx fifo not enough free bytes! (z1=%d, z2=%d)\n",*z1,*z2);
+-	return;
+-    }
+-    
+-    newz1 = (*z1 + count) & hfc_ZMASK;
+-    newf1 = ((*f1 + 1) & hfc_MAX_DFRAMES) | (hfc_MAX_DFRAMES + 1);	// next frame
+-    
+-    if (count > 0) {
+-	if (debug) {
+-    	    printk(KERN_CRIT "zaphfc: card %d TX [ ", hfctmp->cardno);
+-	    for (x=0; x<count; x++) {
++static void hfc_dch_tx(struct hfc_card *hfctmp){
++    struct dch *chtmp=&hfctmp->dch;
++    u8 tx_f2_v;
++    u16 x;
++
++    if(hfctmp->ztdev->chans[2].bytes2transmit){
++	if(debug){
++    	    printk(KERN_CRIT "zaphfc[%d]: card TX [ ",hfctmp->cardno);
++	    for(x=0;x<hfctmp->ztdev->chans[2].bytes2transmit;x++){
+ 		printk("%#2x ",hfctmp->dtransbuf[x]);
+ 	    }
+-	    if (hfctmp->ztdev->chans[2].eoftx == 1) {
+-		printk("] %d bytes\n", count);
+-	    } else {
+-		printk("..] %d bytes\n", count);
+-	    }
+-	}
+-	maxlen = hfc_D_FIFO_SIZE - *z1;
+-	if (maxlen > count) {
+-	    maxlen = count;
++	    printk("] %d bytes\n",hfctmp->ztdev->chans[2].bytes2transmit);
+ 	}
+-	memcpy((char *)(hfctmp->fifos + hfc_FIFO_DTX_ZOFF + *z1),hfctmp->ztdev->chans[2].writechunk, maxlen);
+-	count -= maxlen;
+-	if (count > 0) {
+-	    memcpy((char *)(hfctmp->fifos + hfc_FIFO_DTX_ZOFF),(char *)(hfctmp->ztdev->chans[2].writechunk + maxlen), count);
++	tx_f2_v=*chtmp->tx.f2.p;
++	if(!(tx_f2_v-chtmp->tx.f1.v+hfc_MAX_DFRAMES+1-1)&(hfc_MAX_DFRAMES+1-1)){
++	    printk(KERN_CRIT "zaphfc[%d]: dchan tx fifo total number of frames exceeded!\n",hfctmp->cardno);
++	}else{
++	    if(((*(volatile u16 *)(hfctmp->fifos+hfc_FIFO_DTX_Z2+tx_f2_v*4)-chtmp->tx.f1.z1.v+hfc_D_FIFO_SIZE-1)&(hfc_D_FIFO_SIZE-1))<hfctmp->ztdev->chans[2].bytes2transmit){
++		printk(KERN_CRIT "zaphfc[%d]: dchan tx fifo not enough space for frame!\n",hfctmp->cardno);
++	    }else{
++		chtmp->tx.f1.v=((chtmp->tx.f1.v+1)&hfc_MAX_DFRAMES)|(hfc_MAX_DFRAMES+1);
++		x=min(hfctmp->ztdev->chans[2].bytes2transmit,hfc_D_FIFO_SIZE-chtmp->tx.f1.z1.v);
++		memcpy(hfctmp->fifos+hfc_FIFO_DTX_ZOFF+chtmp->tx.f1.z1.v,hfctmp->ztdev->chans[2].writechunk,x);
++		memcpy(hfctmp->fifos+hfc_FIFO_DTX_ZOFF,hfctmp->ztdev->chans[2].writechunk+x,hfctmp->ztdev->chans[2].bytes2transmit-x);
++		*(volatile u16 *)(hfctmp->fifos+hfc_FIFO_DTX_Z2+chtmp->tx.f1.v*4)=chtmp->tx.f1.z1.v;
++		chtmp->tx.f1.z1.v=(chtmp->tx.f1.z1.v+hfctmp->ztdev->chans[2].bytes2transmit+hfc_D_FIFO_SIZE)&(hfc_D_FIFO_SIZE-1);
++		*(volatile u16 *)(hfctmp->fifos+hfc_FIFO_DTX_Z1+chtmp->tx.f1.v*4)=chtmp->tx.f1.z1.v;
++		*chtmp->tx.f1.p=chtmp->tx.f1.v;
++	    }
+ 	}
+     }
+-
+-    *z1 = newz1;
+-
+-    if (hfctmp->ztdev->chans[2].eoftx == 1) {
+-	*f1 = newf1;
+-	z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DTX_Z1 + (*f1 * 4));
+-	*z1 = newz1;
+-	hfctmp->ztdev->chans[2].eoftx = 0;
+-    }
+-//    printk(KERN_CRIT "zaphfc: dchan tx fifo (f1=%d, f2=%d, z1=%d, z2=%d)\n",(*f1) & hfc_FMASK,(*f2) & hfc_FMASK, *z1, *z2);
+-    return;    
+ }
+ 
+-/* receive a complete hdlc frame, skip broken or short frames */
+-static void hfc_drec(struct hfc_card *hfctmp) {
+-    int count=0, maxlen=0, framelen=0;
+-    unsigned char *f1, *f2, *crcstat;
+-    unsigned short *z1, *z2, oldz2, newz2;
++static void hfc_dch_rx(struct hfc_card *hfctmp){
++    struct dch *chtmp=&hfctmp->dch;
++    u16 size;
+ 
+     hfctmp->ztdev->chans[2].bytes2receive=0;
+-    hfctmp->ztdev->chans[2].eofrx = 0;
+-
+-    /* put the received data into the zaptel buffer
+-       we'll call zt_receive() later when the timer fires. */
+-    f1 = (char *)(hfctmp->fifos + hfc_FIFO_DRX_F1);
+-    f2 = (char *)(hfctmp->fifos + hfc_FIFO_DRX_F2);
+-
+-    if (*f1 == *f2) return; /* nothing received, strange eh? */
+-
+-    z1 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DRX_Z1 + (*f2 * 4));
+-    z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DRX_Z2 + (*f2 * 4));
+-    
+-    /* calculate length of frame, including 2 bytes CRC and 1 byte STAT */
+-    count = *z1 - *z2;
+-    
+-    if (count < 0) { 
+-	count += hfc_D_FIFO_SIZE; /* ring buffer wrapped */
+-    }
+-    count++;
+-    framelen = count;
+-
+-    crcstat = (char *)(hfctmp->fifos + hfc_FIFO_DRX_ZOFF + *z1);
+-
+-    if ((framelen < 4) || (*crcstat != 0x0)) {
+-	/* the frame is too short for a valid HDLC frame or the CRC is borked */
+-	printk(KERN_CRIT "zaphfc: empty HDLC frame or bad CRC received (framelen = %d, stat = %#x, card = %d).\n", framelen, *crcstat, hfctmp->cardno);
+-	oldz2 = *z2;
+-	*f2 = ((*f2 + 1) & hfc_MAX_DFRAMES) | (hfc_MAX_DFRAMES + 1);	/* NEXT!!! */
+-        // recalculate z2, because Z2 is a function of F2 Z2(F2) and we INCed F2!!!
+-	z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DRX_Z2 + (*f2 * 4));
+-	*z2 = (oldz2 + framelen) & hfc_ZMASK;
+-	hfctmp->drecinframe = 0;
+-	hfctmp->regs.int_drec--;
+-	/* skip short or broken frames */
+-        hfctmp->ztdev->chans[2].bytes2receive = 0; 
+-	return;
+-    }
+-
+-    count -= 1;	/* strip STAT */
+-    hfctmp->ztdev->chans[2].eofrx = 1;
+-
+-    if (count + *z2 <= hfc_D_FIFO_SIZE) {
+-	maxlen = count;
+-    } else {
+-	maxlen = hfc_D_FIFO_SIZE - *z2;
++    hfctmp->ztdev->chans[2].eofrx=0;
++    if(*chtmp->rx.f1.p==chtmp->rx.f2.v){
++	hfctmp->regs.int_drec=0;
++    }else{
++	size=((*(volatile u16 *)(hfctmp->fifos+hfc_FIFO_DRX_Z1+chtmp->rx.f2.v*4)-chtmp->rx.f2.z2.v+hfc_D_FIFO_SIZE)&(hfc_D_FIFO_SIZE-1))+1;
++	if(size<4){
++	    printk(KERN_CRIT "zaphfc[%d]: empty HDLC frame received.\n",hfctmp->cardno);
++	}else{
++	    u16 x=min(size,(u16)(hfc_D_FIFO_SIZE-chtmp->rx.f2.z2.v));
++	    memcpy(hfctmp->drecbuf,hfctmp->fifos+hfc_FIFO_DRX_ZOFF+chtmp->rx.f2.z2.v,x);
++	    memcpy(hfctmp->drecbuf+x,hfctmp->fifos+hfc_FIFO_DRX_ZOFF,size-x);
++	    if(hfctmp->drecbuf[size-1]){
++		printk(KERN_CRIT "zaphfc[%d]: received d channel frame with bad CRC.\n",hfctmp->cardno);
++	    }else{
++		hfctmp->ztdev->chans[2].bytes2receive=size-1;
++		hfctmp->ztdev->chans[2].eofrx=1;
++	    }
++	}
++	chtmp->rx.f2.z2.v=(chtmp->rx.f2.z2.v+size)&(hfc_D_FIFO_SIZE-1);
++	chtmp->rx.f2.v=((chtmp->rx.f2.v+1)&hfc_MAX_DFRAMES)|(hfc_MAX_DFRAMES+1);
+     }
+-
+-    /* copy first part */
+-    memcpy(hfctmp->drecbuf, (char *)(hfctmp->fifos + hfc_FIFO_DRX_ZOFF + *z2), maxlen);
+-    hfctmp->ztdev->chans[2].bytes2receive += maxlen; 
+-    
+-    count -= maxlen;
+-    if (count > 0) {
+-	/* ring buffer wrapped, copy rest from start of d fifo */
+-	memcpy(hfctmp->drecbuf + maxlen, (char *)(hfctmp->fifos + hfc_FIFO_DRX_ZOFF), count);
+-	hfctmp->ztdev->chans[2].bytes2receive += count; 
+-    }
+-
+-    /* frame read */
+-    oldz2 = *z2;
+-    newz2 = (oldz2 + framelen) & hfc_ZMASK;
+-    *f2 = ((*f2 + 1) & hfc_MAX_DFRAMES) | (hfc_MAX_DFRAMES + 1);	/* NEXT!!! */
+-    /* recalculate z2, because Z2 is a function of F2 Z2(F2) and we INCed F2!!! */
+-    z2 = (unsigned short *)(hfctmp->fifos + hfc_FIFO_DRX_Z2 + (*f2 * 4));
+-    *z2 = newz2;
+-    hfctmp->drecinframe = 0;
+-    hfctmp->regs.int_drec--; 
+ }
+ 
+-#ifndef RTAITIMING
+-ZAP_IRQ_HANDLER(hfc_interrupt) {
+-    struct hfc_card *hfctmp = dev_id;
+-    unsigned long flags = 0;
+-    unsigned char stat;
++/*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
++
++#ifdef LINUX26
++static irqreturn_t hfc_interrupt(int irq, void *dev_id, struct pt_regs *regs) {
+ #else
+-static void hfc_service(struct hfc_card *hfctmp) {
++static void hfc_interrupt(int irq, void *dev_id, struct pt_regs *regs) {
+ #endif
++    struct hfc_card *hfctmp = dev_id;
++    struct hfc_card *hfctmp2;
+     struct zt_hfc *zthfc;
+-    unsigned char s1, s2, l1state;
++    unsigned char stat, s1, s2, l1state;
++    unsigned long flags;
++    unsigned long flags2=0;
+     int x;
+ 
+     if (!hfctmp) {
+-#ifndef RTAITIMING
+ #ifdef LINUX26
+ 		return IRQ_NONE;
+ #else
+ 		return;
+ #endif		
+-#else
+-	/* rtai */
+-	return;
+-#endif
+     }
+ 
+     if (!hfctmp->pci_io) {
+ 	    printk(KERN_WARNING "%s: IO-mem disabled, cannot handle interrupt\n",
+ 		   __FUNCTION__);
+-#ifndef RTAITIMING
+ #ifdef LINUX26
+ 	    return IRQ_NONE;
+ #else
+ 	    return;
+ #endif		
+-#else
+-	/* rtai */
+-	return;
+-#endif
+     }
+-    
+-    /*	we assume a few things in this irq handler:
+-	- the hfc-pci will only generate "timer" irqs (proc/non-proc)
+-	- we need to use every 8th IRQ (to generate 1khz timing)
+-	OR
+-	- if we use rtai for timing the hfc-pci will not generate ANY irq,
+-	  instead rtai will call this "fake" irq with a 1khz realtime timer. :)
+-	- rtai will directly service the card, not like it used to by triggering
+-	  the linux irq
+-    */
+ 
+-#ifndef RTAITIMING
+     spin_lock_irqsave(&hfctmp->lock, flags);
+     stat = hfc_inb(hfctmp, hfc_STATUS);
+-
+     if ((stat & hfc_STATUS_ANYINT) == 0) {
+         // maybe we are sharing the irq
+ 	spin_unlock_irqrestore(&hfctmp->lock,flags);
+@@ -605,8 +458,6 @@
+ 	return;
+ #endif		
+     }
+-#endif
+-
+     s1 = hfc_inb(hfctmp, hfc_INT_S1);
+     s2 = hfc_inb(hfctmp, hfc_INT_S2); 
+     if (s1 != 0) {
+@@ -625,18 +476,10 @@
+ 		}
+ 		switch (l1state) {
+ 		    case 3:
+-#ifdef RTAITIMING
+-			sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT] layer 1 ACTIVATED (G%d) [realtime]", hfctmp->cardno, l1state);
+-#else
+ 			sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT] layer 1 ACTIVATED (G%d)", hfctmp->cardno, l1state);
+-#endif
+ 			break;
+ 		    default:
+-#ifdef RTAITIMING
+-			sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT] layer 1 DEACTIVATED (G%d) [realtime]", hfctmp->cardno, l1state);
+-#else
+ 			sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT] layer 1 DEACTIVATED (G%d)", hfctmp->cardno, l1state);
+-#endif
+ 		}
+ 		if (l1state == 2) {
+ 		    hfc_outb(hfctmp, hfc_STATES, hfc_STATES_ACTIVATE | hfc_STATES_DO_ACTION | hfc_STATES_NT_G2_G3);
+@@ -650,18 +493,10 @@
+ 		}
+ 		switch (l1state) {
+ 		    case 7:
+-#ifdef RTAITIMING
+-			sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE] layer 1 ACTIVATED (F%d) [realtime]", hfctmp->cardno, l1state);
+-#else
+ 			sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE] layer 1 ACTIVATED (F%d)", hfctmp->cardno, l1state);
+-#endif
+ 			break;
+ 		    default:
+-#ifdef RTAITIMING
+-			sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE] layer 1 DEACTIVATED (F%d) [realtime]", hfctmp->cardno, l1state);
+-#else
+ 			sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE] layer 1 DEACTIVATED (F%d)", hfctmp->cardno, l1state);
+-#endif
+ 		}
+ 		if (l1state == 3) {
+ 		    hfc_outb(hfctmp, hfc_STATES, hfc_STATES_DO_ACTION | hfc_STATES_ACTIVATE);
+@@ -671,7 +506,7 @@
+ 	}
+ 	if (s1 & hfc_INTS_DREC) {
+ 	    // D chan RX (bit 5)
+-	    hfctmp->regs.int_drec++;
++	    hfctmp->regs.int_drec = 1;
+ 	    // mr. zapata there is something for you!
+ 	//    printk(KERN_CRIT "d chan rx\n");		    
+ 	}
+@@ -692,14 +527,10 @@
+ 	    // B1 chan TX (bit 0)
+ 	}
+     }
+-#ifdef RTAITIMING
+-    /* fake an irq */
+-    s2 |= hfc_M2_PROC_TRANS;
+-#endif
+     if (s2 != 0) {
+ 	if (s2 & hfc_M2_PMESEL) {
+ 	    // kaboom irq (bit 7)
+-	    printk(KERN_CRIT "zaphfc: sync lost, pci performance too low. you might have some cpu throtteling enabled.\n");
++	    // printk(KERN_CRIT "zaphfc: sync lost, pci performance too low. you might have some cpu throtteling enabled.\n");
+ 	}
+ 	if (s2 & hfc_M2_GCI_MON_REC) {
+ 	    // RxR monitor channel (bit 2)
+@@ -707,32 +538,30 @@
+ 	if (s2 & hfc_M2_GCI_I_CHG) {
+ 	    // GCI I-change  (bit 1)
+ 	}
+-	if (s2 & hfc_M2_PROC_TRANS) {
++	if((s2&hfc_M2_PROC_TRANS)&&(hfctmp->cardno==timer_card)){
+ 	    // processing/non-processing transition  (bit 0)
+-	    hfctmp->ticks++;
+-#ifndef RTAITIMING
+-	    if (hfctmp->ticks > 7) {
+-		// welcome to zaptel timing :)
+-#endif
+-	    	hfctmp->ticks = 0;
+-
++	hfctmp2=hfctmp;
++	hfctmp=hfc_dev_list;
++	while(hfctmp){
++	    if(hfctmp->active){
++	    if(hfctmp!=hfctmp2)spin_lock_irqsave(&hfctmp->lock, flags2);
++	    if(hfc_bch_check(hfctmp)){
+ 		if (hfctmp->ztdev->span.flags & ZT_FLAG_RUNNING) {
+ 		    // clear dchan buffer
++	//	    memset(hfctmp->drecbuf, 0x0, sizeof(hfctmp->drecbuf));
++
+ 		    hfctmp->ztdev->chans[2].bytes2transmit = 0;
+ 		    hfctmp->ztdev->chans[2].maxbytes2transmit = hfc_D_FIFO_SIZE;
+ 
+ 		    zt_transmit(&(hfctmp->ztdev->span));
+ 
+-		    hfc_btrans(hfctmp,1);
+-		    hfc_btrans(hfctmp,2);
+-		    hfc_dtrans(hfctmp);
++		    hfc_bch_tx(hfctmp);
++		    hfc_dch_tx(hfctmp);
+ 		}
+-
+-		hfc_brec(hfctmp,1);
+-		hfc_brec(hfctmp,2);
+-		if (hfctmp->regs.int_drec > 0) {
++		hfc_bch_rx(hfctmp);
++		if (hfctmp->regs.int_drec) {
+ 		    // dchan data to read
+-		    hfc_drec(hfctmp);
++		    hfc_dch_rx(hfctmp);
+ 		    if (hfctmp->ztdev->chans[2].bytes2receive > 0) {
+ 			    if (debug) {
+     				printk(KERN_CRIT "zaphfc: card %d RX [ ", hfctmp->cardno);
+@@ -757,19 +586,18 @@
+ 		if (hfctmp->ztdev->span.flags & ZT_FLAG_RUNNING) {
+ 		    zt_receive(&(hfctmp->ztdev->span));
+ 		}
+-		
+-#ifndef RTAITIMING
+ 	    }
+-#endif
++	    if(hfctmp!=hfctmp2)spin_unlock_irqrestore(&hfctmp->lock,flags2);
++	    }
++	    hfctmp=hfctmp->next;
++	}
++	hfctmp=hfctmp2;
+ 	}
+-
+     }
+-#ifndef RTAITIMING
+     spin_unlock_irqrestore(&hfctmp->lock,flags);
+ #ifdef LINUX26
+ 	return IRQ_RETVAL(1);
+ #endif		
+-#endif
+ }
+ 
+ 
+@@ -826,22 +654,21 @@
+     }
+     alreadyrunning = span->flags & ZT_FLAG_RUNNING;
+     
+-    if (!alreadyrunning) {
+-	span->chans[2].flags &= ~ZT_FLAG_HDLC;
+-	span->chans[2].flags |= ZT_FLAG_BRIDCHAN;
+-	
+-	span->flags |= ZT_FLAG_RUNNING;
++    if (alreadyrunning) return 0;
+ 
+-	hfctmp->ticks = -2;
+-	hfctmp->clicks = 0;
+-	hfctmp->regs.fifo_en = hfc_FIFOEN_D | hfc_FIFOEN_B1 | hfc_FIFOEN_B2;
+-        hfc_outb(hfctmp, hfc_FIFO_EN, hfctmp->regs.fifo_en);
+-    } else {
+-	return 0;
+-    }
++    span->chans[2].flags &= ~ZT_FLAG_HDLC;
++    span->chans[2].flags |= ZT_FLAG_BRIDCHAN;
++    
++    span->flags |= ZT_FLAG_RUNNING;
++
++    hfctmp->ticks = -2;	
++    hfctmp->regs.fifo_en = hfc_FIFOEN_D | hfc_FIFOEN_B1 | hfc_FIFOEN_B2;
++    hfc_outb(hfctmp, hfc_FIFO_EN, hfctmp->regs.fifo_en);
+ 
++    hfc_bch_init(hfctmp);
+     // drivers, start engines!
+     hfc_outb(hfctmp, hfc_STATES, hfc_STATES_DO_ACTION | hfc_STATES_ACTIVATE);
++    hfctmp->active=1;
+     return 0;
+ }
+ 
+@@ -871,17 +698,9 @@
+ 
+     sprintf(zthfc->span.name, "ZTHFC%d", hfc_dev_count + 1);
+     if (hfctmp->regs.nt_mode == 1) {
+-#ifdef RTAITIMING
+-	sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT] [realtime]", hfc_dev_count + 1);
+-#else
+ 	sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT]", hfc_dev_count + 1);
+-#endif
+     } else {
+-#ifdef RTAITIMING
+-	sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE] [realtime]", hfc_dev_count + 1);
+-#else
+ 	sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE]", hfc_dev_count + 1);
+-#endif
+     }
+ 
+     zthfc->span.spanconfig = zthfc_spanconfig;
+@@ -918,32 +737,6 @@
+     return 0;
+ }
+ 
+-#ifdef RTAITIMING
+-#define TICK_PERIOD  1000000
+-#define TICK_PERIOD2 1000000000
+-#define TASK_PRIORITY 1
+-#define STACK_SIZE 10000
+-
+-static RT_TASK rt_task;
+-static struct hfc_card *rtai_hfc_list[hfc_MAX_CARDS];
+-static unsigned char rtai_hfc_counter = 0;
+-
+-static void rtai_register_hfc(struct hfc_card *hfctmp) {
+-    rtai_hfc_list[rtai_hfc_counter++] = hfctmp;
+-}
+-
+-static void rtai_loop(int t) {
+-    int i=0;
+-    for (;;) {
+-	for (i=0; i < rtai_hfc_counter; i++) {
+-	    if (rtai_hfc_list[i] != NULL)
+-		hfc_service(rtai_hfc_list[i]);
+-	}
+-        rt_task_wait_period();
+-    }
+-}
+-#endif
+-
+ int hfc_findCards(int pcivendor, int pcidevice, char *vendor_name, char *card_name) {
+     struct pci_dev *tmp;
+     struct hfc_card *hfctmp = NULL;
+@@ -959,9 +752,9 @@
+ 	}
+ 	pci_set_master(tmp);
+ 
+-	hfctmp = kmalloc(sizeof(struct hfc_card), GFP_KERNEL);
++	hfctmp = vmalloc(sizeof(struct hfc_card));
+ 	if (!hfctmp) {
+-	    printk(KERN_WARNING "zaphfc: unable to kmalloc!\n");
++	    printk(KERN_WARNING "zaphfc: unable to vmalloc!\n");
+ 	    pci_disable_device(tmp);
+ 	    multi_hfc = NULL;
+ 	    return -ENOMEM;
+@@ -969,6 +762,7 @@
+ 	memset(hfctmp, 0x0, sizeof(struct hfc_card));
+ 	spin_lock_init(&hfctmp->lock);
+ 	
++	hfctmp->active=0;
+ 	hfctmp->pcidev = tmp;
+ 	hfctmp->pcibus = tmp->bus->number;
+ 	hfctmp->pcidevfn = tmp->devfn; 
+@@ -982,49 +776,39 @@
+ 	hfctmp->pci_io = (char *) tmp->resource[1].start;
+ 	if (!hfctmp->pci_io) {
+ 	    printk(KERN_WARNING "zaphfc: no iomem!\n");
+-	    kfree(hfctmp);
++	    vfree(hfctmp);
+ 	    pci_disable_device(tmp);
+ 	    multi_hfc = NULL;
+ 	    return -1;
+ 	}
+-	
+-	hfctmp->fifomem = kmalloc(65536, GFP_KERNEL);
+-	if (!hfctmp->fifomem) {
+-	    printk(KERN_WARNING "zaphfc: unable to kmalloc fifomem!\n");
+-	    kfree(hfctmp);
++
++	hfctmp->fifos=(void *)__get_free_pages(GFP_KERNEL,log2(hfc_FIFO_MEM_SIZE_PAGES));
++	if (!hfctmp->fifos) {
++	    printk(KERN_WARNING "zaphfc: unable to __get_free_pages fifomem!\n");
++	    vfree(hfctmp);
+ 	    pci_disable_device(tmp);
+ 	    multi_hfc = NULL;
+ 	    return -ENOMEM;
+ 	} else {
+-	    memset(hfctmp->fifomem, 0x0, 65536);
+-	    hfctmp->fifos = (void *)(((ulong) hfctmp->fifomem) & ~0x7FFF) + 0x8000;
+ 	    pci_write_config_dword(hfctmp->pcidev, 0x80, (u_int) virt_to_bus(hfctmp->fifos));
+ 	    hfctmp->pci_io = ioremap((ulong) hfctmp->pci_io, 256);
+ 	}
+ 
+-#ifdef RTAITIMING
+-	/* we need no stinking irq */
+-	hfctmp->irq = 0;
+-#else
+ 	if (request_irq(hfctmp->irq, &hfc_interrupt, SA_INTERRUPT | SA_SHIRQ, "zaphfc", hfctmp)) {
+ 	    printk(KERN_WARNING "zaphfc: unable to register irq\n");
+-	    kfree(hfctmp->fifomem);
+-	    kfree(hfctmp);
++	    free_pages((unsigned long)hfctmp->fifos,log2(hfc_FIFO_MEM_SIZE_PAGES));
++	    vfree(hfctmp);
+ 	    iounmap((void *) hfctmp->pci_io);
+ 	    pci_disable_device(tmp);
+ 	    multi_hfc = NULL;
+ 	    return -EIO;
+ 	}
+-#endif
+ 
+-#ifdef RTAITIMING
+-	rtai_register_hfc(hfctmp);
+-#endif
+ 	printk(KERN_INFO
+-		       "zaphfc: %s %s configured at mem %lx fifo %lx(%#x) IRQ %d HZ %d\n",
++		       "zaphfc: %s %s configured at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n",
+ 			vendor_name, card_name,
+-		       (unsigned long) hfctmp->pci_io,
+-		       (unsigned long) hfctmp->fifos,
++		       (u_int) hfctmp->pci_io,
++		       (u_int) hfctmp->fifos,
+ 		       (u_int) virt_to_bus(hfctmp->fifos),
+ 		       hfctmp->irq, HZ); 
+ 	pci_write_config_word(hfctmp->pcidev, PCI_COMMAND, PCI_COMMAND_MEMORY);	// enable memio
+@@ -1041,11 +825,21 @@
+ 	    hfctmp->regs.nt_mode = 0;
+ 	}
+ 
+-	zthfc = kmalloc(sizeof(struct zt_hfc),GFP_KERNEL);
++	if(sync_slave&(1<<hfc_dev_count)){
++	    printk(KERN_INFO "zaphfc: Card %d configured for slave mode\n",hfc_dev_count);
++	    hfctmp->regs.mst_mode=hfc_MST_MODE_SLAVE|hfc_MST_MODE_F0_LONG_DURATION;
++	    hfctmp->regs.mst_emod=hfc_MST_EMOD_SLOW_CLOCK_ADJ;
++	}else{
++	    printk(KERN_INFO "zaphfc: Card %d configured for master mode\n",hfc_dev_count);
++	    hfctmp->regs.mst_mode=hfc_MST_MODE_MASTER|hfc_MST_MODE_F0_LONG_DURATION;
++	    hfctmp->regs.mst_emod=0;
++	}
++
++	zthfc = vmalloc(sizeof(struct zt_hfc));
+ 	if (!zthfc) {
+-	    printk(KERN_CRIT "zaphfc: unable to kmalloc!\n");
++	    printk(KERN_CRIT "zaphfc: unable to vmalloc!\n");
+ 	    hfc_shutdownCard(hfctmp);
+-	    kfree(hfctmp);
++	    vfree(hfctmp);
+ 	    multi_hfc = NULL;
+ 	    return -ENOMEM;
+ 	}
+@@ -1071,7 +865,6 @@
+ 	memset(hfctmp->btransbuf[1], 0x0, sizeof(hfctmp->btransbuf[1]));
+ 	hfctmp->ztdev->chans[1].writechunk = hfctmp->btransbuf[1];
+ 
+-
+ 	hfc_registerCard(hfctmp);
+ 	hfc_resetCard(hfctmp);
+ 	tmp = pci_find_device(pcivendor, pcidevice, multi_hfc);
+@@ -1079,58 +872,42 @@
+     return 0;
+ }
+ 
+-
+-
+ int init_module(void) {
+     int i = 0;
+-#ifdef RTAITIMING
+-    RTIME tick_period;
+-    for (i=0; i < hfc_MAX_CARDS; i++) {
+-	rtai_hfc_list[i] = NULL;
++    if(jitterbuffer<1){
++	printk(KERN_INFO "zaphfc: invalid jitterbuffer size specified: %d - changing to minimum of 1\n",jitterbuffer);
++	jitterbuffer=1;
++    }else if(jitterbuffer>500){
++	printk(KERN_INFO "zaphfc: invalid jitterbuffer size specified: %d - changing to maximum of 500\n",jitterbuffer);
++	jitterbuffer=500;
+     }
+-    rt_set_periodic_mode();
+-#endif
+-    i = 0;
++    printk(KERN_INFO "zaphfc: jitterbuffer size: %d\n",jitterbuffer);
+     while (id_list[i].vendor_id) {
+ 	multi_hfc = NULL;
+ 	hfc_findCards(id_list[i].vendor_id, id_list[i].device_id, id_list[i].vendor_name, id_list[i].card_name);
+ 	i++;
+     }
+-#ifdef RTAITIMING
+-    for (i=0; i < hfc_MAX_CARDS; i++) {
+-        if (rtai_hfc_list[i]) {
+-	    printk(KERN_INFO
+-		       "zaphfc: configured %d at mem %#x fifo %#x(%#x) for realtime servicing\n",
+-			rtai_hfc_list[i]->cardno,
+-		       (u_int) rtai_hfc_list[i]->pci_io,
+-		       (u_int) rtai_hfc_list[i]->fifos,
+-		       (u_int) virt_to_bus(rtai_hfc_list[i]->fifos));
+-
+-	}
+-    }
+-    rt_task_init(&rt_task, rtai_loop, 1, STACK_SIZE, TASK_PRIORITY, 0, 0);
+-    tick_period = start_rt_timer(nano2count(TICK_PERIOD));
+-    rt_task_make_periodic(&rt_task, rt_get_time() + tick_period, tick_period);
+-#endif
+     printk(KERN_INFO "zaphfc: %d hfc-pci card(s) in this box.\n", hfc_dev_count);
+     return 0;
+ }
+ 
+ void cleanup_module(void) {
+     struct hfc_card *tmpcard;
+-#ifdef RTAITIMING
+-    stop_rt_timer();
+-    rt_task_delete(&rt_task);
+-#endif
++
+     printk(KERN_INFO "zaphfc: stop\n");
+ //    spin_lock(&registerlock);
++    tmpcard=hfc_dev_list;
++    while(tmpcard){
++	hfc_shutdownCard1(tmpcard);
++	tmpcard=tmpcard->next;
++    }
+     while (hfc_dev_list != NULL) {
+ 	if (hfc_dev_list == NULL) break;
+-	hfc_shutdownCard(hfc_dev_list);
++	hfc_shutdownCard2(hfc_dev_list);
+ 	tmpcard = hfc_dev_list;
+ 	hfc_dev_list = hfc_dev_list->next;
+ 	if (tmpcard != NULL) {
+-	    kfree(tmpcard);
++	    vfree(tmpcard);
+ 	    tmpcard = NULL;
+ 	    printk(KERN_INFO "zaphfc: freed one card.\n");
+ 	}
+@@ -1141,11 +918,17 @@
+ 
+ 
+ #ifdef LINUX26
+-module_param(modes, int, 0600);
++module_param(modes, int, 0400);
+ module_param(debug, int, 0600);
++module_param(sync_slave, int, 0400);
++module_param(timer_card, int, 0400);
++module_param(jitterbuffer, int, 0400);
+ #else
+ MODULE_PARM(modes,"i");
+ MODULE_PARM(debug,"i");
++MODULE_PARM(sync_slave,"i");
++MODULE_PARM(timer_card,"i");
++MODULE_PARM(jitterbuffer,"i");
+ #endif
+ 
+ MODULE_DESCRIPTION("HFC-S PCI A Zaptel Driver");
+@@ -1153,3 +936,6 @@
+ #ifdef MODULE_LICENSE
+ MODULE_LICENSE("GPL");
+ #endif	
++
++/* vim:set sw=4: */
++
+diff -urN bristuff-0.4.0-test1/zaphfc/zaphfc.h zaphfc_0.4.0-test1_florz-13/zaphfc.h
+--- bristuff-0.4.0-test1/zaphfc/zaphfc.h	2005-02-26 23:30:32.000000000 +0100
++++ zaphfc_0.4.0-test1_florz-13/zaphfc.h	2005-03-02 20:43:04.000000000 +0100
+@@ -135,8 +135,12 @@
+ /* bits in HFCD_MST_MODE */
+ #define hfc_MST_MODE_MASTER	     0x01
+ #define hfc_MST_MODE_SLAVE         0x00
++#define hfc_MST_MODE_F0_LONG_DURATION         0x08
+ /* remaining bits are for codecs control */
+ 
++/* bits in HFCD_MST_EMOD */
++#define hfc_MST_EMOD_SLOW_CLOCK_ADJ	0x01
++
+ /* bits in HFCD_SCTRL */
+ #define hfc_SCTRL_B1_ENA	     0x01
+ #define hfc_SCTRL_B2_ENA	     0x02
+@@ -236,6 +240,9 @@
+ #define hfc_BTRANS_THRESHOLD 128
+ #define hfc_BTRANS_THRESMASK 0x00
+ 
++#define hfc_FIFO_MEM_SIZE_BYTES (32*1024)
++#define hfc_FIFO_MEM_SIZE_PAGES ((hfc_FIFO_MEM_SIZE_BYTES+PAGE_SIZE-1)/PAGE_SIZE)
++
+ /* Structures */
+ 
+ typedef struct hfc_regs {
+@@ -249,20 +256,67 @@
+     unsigned char connect;
+     unsigned char trm;
+     unsigned char mst_mode;
++    unsigned char mst_emod;
+     unsigned char bswapped;
+     unsigned char nt_mode;
+     unsigned char int_drec;
+ } hfc_regs;
+ 
++struct bch {
++    int fill_fifo,checkcnt,initialized;
++    struct {
++	u16 z2;
++	struct {
++	    volatile u16 *z1p;
++	    volatile u8 *fifo_base;
++	    int filled;
++	} c[2];
++	int diff;
++    } rx;
++    struct {
++	u16 z1;
++	struct {
++	    volatile u16 *z1p,*z2p;
++	    volatile u8 *fifo_base;
++	    int filled;
++	} c[2];
++	int diff;
++    } tx;
++};
++
++struct dch {
++    struct {
++	struct {
++	    volatile u8 *p;
++	} f1;
++	struct {
++	    u8 v;
++	    struct {
++		u16 v;
++	    } z2;
++	} f2;
++    } rx;
++    struct {
++	struct {
++	    u8 v;
++	    volatile u8 *p;
++	    struct {
++		u16 v;
++	    } z1;
++	} f1;
++	struct {
++	    volatile u8 *p;
++	} f2;
++    } tx;
++};
++
+ typedef struct hfc_card {
+     spinlock_t lock;
+     unsigned int irq;
+     unsigned int iomem;
+     int ticks;		
+-    int clicks;		
+     unsigned char *pci_io;
+-    void *fifomem;		// start of the shared mem
+-    volatile void *fifos;	// 32k aligned mem for the fifos
++    void *fifos;		// 32k aligned mem for the fifos
+     struct hfc_regs regs;
+     unsigned int pcibus;
+     unsigned int pcidevfn;
+@@ -274,6 +328,9 @@
+     unsigned char brecbuf[2][ZT_CHUNKSIZE];
+     unsigned char btransbuf[2][ZT_CHUNKSIZE];
+     unsigned char cardno;
++    int active;
++    struct bch bch;
++    struct dch dch;
+     struct hfc_card *next;
+ } hfc_card;
+ 
+@@ -284,6 +341,5 @@
+     struct hfc_card *card;
+ } zt_hfc;
+ 
+-/* tune this */
+-#define hfc_BCHAN_BUFFER	8
+-#define hfc_MAX_CARDS		8
++/* vim:set sw=4: */
++




More information about the Pkg-voip-commits mailing list