[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(®isterlock);
+ }
+
+-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(®isterlock);
++ 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