From 31a3e84249faa0ee92c0db6fe06ead9c2e76838f Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Mon, 5 Mar 2018 10:20:24 +0000 Subject: main/dahdi-linux-vanilla: rebuild against kernel 4.14.24 --- main/dahdi-linux-vanilla/APKBUILD | 6 +- main/dahdi-linux-vanilla/zaphfc-dahdi-flortz.diff | 1232 -------------------- main/dahdi-linux-vanilla/zaphfc-dahdi-flortz.patch | 1232 ++++++++++++++++++++ 3 files changed, 1235 insertions(+), 1235 deletions(-) delete mode 100644 main/dahdi-linux-vanilla/zaphfc-dahdi-flortz.diff create mode 100644 main/dahdi-linux-vanilla/zaphfc-dahdi-flortz.patch (limited to 'main/dahdi-linux-vanilla') diff --git a/main/dahdi-linux-vanilla/APKBUILD b/main/dahdi-linux-vanilla/APKBUILD index d9c89d631d..d64212281f 100644 --- a/main/dahdi-linux-vanilla/APKBUILD +++ b/main/dahdi-linux-vanilla/APKBUILD @@ -8,7 +8,7 @@ _rel=0 _flavor=${FLAVOR:-vanilla} _kpkg=linux-$_flavor -_kver=4.14.20 +_kver=4.14.24 _krel=0 _kpkgver="$_kver-r$_krel" @@ -32,7 +32,7 @@ source="http://downloads.digium.com/pub/telephony/dahdi-linux/releases/${_name}- dahdi-depmod.patch dahdi-bri_dchan.patch dahdi-zaphfc.patch - zaphfc-dahdi-flortz.diff + zaphfc-dahdi-flortz.patch zaphfc-dahdi-2.4.0.patch zaphfc-dahdi-2.5.0.patch zaphfc-dahdi-2.6.0.patch @@ -90,7 +90,7 @@ sha512sums="db15d9237f157b5349de8f4cdb45573ed42e1dd25c83f900835c7e15637a19e1e95c aba01eb90d9db1c595ff22078c76aadb20900486b5794d38b7ee61fa30d2fb51be318a4d059246017640447aee03fb09bb5514c818e3caa1cd98e331ec065173 dahdi-depmod.patch fa2fa9e96eefc0f31a1a4a8f8f44e77936f6da0d7b74fe3c3d1f0de085621744ae4367932ac97a10b7f96b7d0954843b0bfe07a251b85434079cc6da29e243ba dahdi-bri_dchan.patch 8ef31c9723237da83954832df5aee1f5daa23f8fefe07a1a191a2c5da2c2308001d68cee83500f7ef43166bfc0d65552b0ca5362789c5c82a7217e09362fd5fe dahdi-zaphfc.patch -f18043fd18a05be7e49daa9d8c96c8a8c45936b14e82e30523e4d88b1620a73147f765d24d2038c4ec0855901e36e8e2b188d596f94437dfb80f6d76ab699d9d zaphfc-dahdi-flortz.diff +f18043fd18a05be7e49daa9d8c96c8a8c45936b14e82e30523e4d88b1620a73147f765d24d2038c4ec0855901e36e8e2b188d596f94437dfb80f6d76ab699d9d zaphfc-dahdi-flortz.patch 8068fcbba81b819bbd14a1a324457d0febd5350d16c6443be035c50f7759010376bd92d3c7ea69b47309e02603e587387b643f64663652e162853515371a6da5 zaphfc-dahdi-2.4.0.patch 95811d56f5567bbab1e6fac89fdc7a4d78252a54a416e884903ae2709f8922f5cd02c492de0bad5c35fdfd52250ec231ed11457e36ba33f8747c3226491882de zaphfc-dahdi-2.5.0.patch 7533c640817f71789c922bb9a5a3b6132b5b47958770929b1c9a50a1e2e6de914e278f466a85ef99759e291e5907c56d60926c74075f4e731a9910a46c1be3ea zaphfc-dahdi-2.6.0.patch diff --git a/main/dahdi-linux-vanilla/zaphfc-dahdi-flortz.diff b/main/dahdi-linux-vanilla/zaphfc-dahdi-flortz.diff deleted file mode 100644 index dc856c97c7..0000000000 --- a/main/dahdi-linux-vanilla/zaphfc-dahdi-flortz.diff +++ /dev/null @@ -1,1232 +0,0 @@ -Index: dahdi-linux-2.1.0.4/drivers/dahdi/zaphfc.h -=================================================================== ---- dahdi-linux-2.1.0.4.orig/drivers/dahdi/zaphfc.h 2009-03-17 18:13:54.000000000 +0200 -+++ dahdi-linux-2.1.0.4/drivers/dahdi/zaphfc.h 2009-03-17 18:14:44.000000000 +0200 -@@ -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][DAHDI_CHUNKSIZE]; - unsigned char btransbuf[2][DAHDI_CHUNKSIZE]; - unsigned char cardno; -+ int active; -+ struct bch bch; -+ struct dch dch; - struct hfc_card *next; - } hfc_card; - -@@ -285,6 +342,3 @@ - struct hfc_card *card; - } dahdi_hfc; - --/* tune this */ --#define hfc_BCHAN_BUFFER 8 --#define hfc_MAX_CARDS 8 -Index: dahdi-linux-2.1.0.4/drivers/dahdi/zaphfc.c -=================================================================== ---- dahdi-linux-2.1.0.4.orig/drivers/dahdi/zaphfc.c 2009-03-17 18:52:47.000000000 +0200 -+++ dahdi-linux-2.1.0.4/drivers/dahdi/zaphfc.c 2009-03-17 18:53:43.000000000 +0200 -@@ -7,19 +7,21 @@ - * - * Klaus-Peter Junghanns - * -+ * Copyright (C) 2004, 2005, 2006 Florian Zumbiehl -+ * - 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 - #include --#ifdef RTAITIMING --#include --#include --#include --#include --#endif - #include - #include - #include -@@ -29,6 +31,8 @@ - - #include - -+#define log2(n) ffz(~(n)) -+ - #if CONFIG_PCI - - #define CLKDEL_TE 0x0f /* CLKDEL in TE mode */ -@@ -70,42 +74,31 @@ - static struct hfc_card *hfc_dev_list = NULL; - static int hfc_dev_count = 0; - static int modes = 0; // all TE -+static int sync_slave = 0; // all master -+static int timer_card = 0; -+static int jitterbuffer = 1; - static int debug = 0; - static struct pci_dev *multi_hfc = NULL; - static DEFINE_SPINLOCK(registerlock); - --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 -@@ -119,8 +112,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; -@@ -130,11 +123,24 @@ - spin_unlock_irqrestore(&hfctmp->lock,flags); - if (hfctmp->ztdev != NULL) { - dahdi_unregister(&hfctmp->ztdev->span); -- kfree(hfctmp->ztdev); -+ vfree(hfctmp->ztdev); - printk(KERN_INFO "unregistered from DAHDI.\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; - -@@ -178,14 +184,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 */ -@@ -197,8 +203,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; -@@ -210,10 +216,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); -@@ -230,368 +234,210 @@ - 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 = DAHDI_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%DAHDI_CHUNKSIZE -+#error hfc_B_FIFO_SIZE is not a multiple of DAHDI_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 = DAHDI_CHUNKSIZE; -- -- if (bytes < DAHDI_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,DAHDI_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 + DAHDI_CHUNKSIZE) { -- /* if the system is too slow to handle it, we will have to drop it all (except 1 DAHDI chunk) */ -- drop = bytes - DAHDI_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%=DAHDI_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<=DAHDI_CHUNKSIZE*jitterbuffer&&chtmp->tx.c[1].filled<=DAHDI_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) { -- dahdi_ec_chunk(&hfctmp->ztdev->chans[0], hfctmp->ztdev->chans[0].readchunk, hfctmp->ztdev->chans[0].writechunk); -- } else { -- dahdi_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,DAHDI_CHUNKSIZE); -+ hfc_bch_inc_z(chtmp->tx.z1,DAHDI_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>=DAHDI_CHUNKSIZE&&chtmp->rx.c[1].filled>=DAHDI_CHUNKSIZE){ -+ if((chtmp->rx.c[0].filled>=DAHDI_CHUNKSIZE*(jitterbuffer+2)&&chtmp->rx.c[1].filled>=DAHDI_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%DAHDI_CHUNKSIZE-DAHDI_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),DAHDI_CHUNKSIZE); -+ dahdi_ec_chunk(&hfctmp->ztdev->chans[x],hfctmp->ztdev->chans[x].readchunk,hfctmp->ztdev->chans[x].writechunk); -+ } -+ hfc_bch_inc_z(chtmp->rx.z2,DAHDI_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; xdch; -+ 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;xztdev->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))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 DAHDI buffer -- we'll call dahdi_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 - DAHDI_IRQ_HANDLER(hfc_interrupt) { - struct hfc_card *hfctmp = dev_id; -- unsigned long flags = 0; -- unsigned char stat; --#else --static void hfc_service(struct hfc_card *hfctmp) { --#endif -+ struct hfc_card *hfctmp2; - struct dahdi_hfc *zthfc; -- unsigned char s1, s2, l1state; -+ unsigned char stat, s1, s2, l1state; -+ unsigned long flags = 0; -+ unsigned long flags2 = 0; - int x; - - if (!hfctmp) { --#ifndef RTAITIMING -- return IRQ_NONE; --#else -- /* rtai */ -- return; --#endif -+ return IRQ_NONE; - } - - if (!hfctmp->pci_io) { - printk(KERN_WARNING "%s: IO-mem disabled, cannot handle interrupt\n", - __FUNCTION__); --#ifndef RTAITIMING - return IRQ_NONE; --#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); - return IRQ_NONE; - } --#endif - - s1 = hfc_inb(hfctmp, hfc_INT_S1); - s2 = hfc_inb(hfctmp, hfc_INT_S2); -@@ -611,18 +457,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); -@@ -636,18 +474,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); -@@ -657,7 +487,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"); - } -@@ -678,14 +508,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) -@@ -693,32 +519,31 @@ - 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 DAHDI timing :) --#endif -- hfctmp->ticks = 0; -- -- if (hfctmp->ztdev->span.flags & DAHDI_FLAG_RUNNING) { -+ 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 & DAHDI_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; - - dahdi_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); -@@ -743,17 +568,16 @@ - if (hfctmp->ztdev->span.flags & DAHDI_FLAG_RUNNING) { - dahdi_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); -- return IRQ_RETVAL(1); --#endif -+ return IRQ_RETVAL(1); - } - - -@@ -802,22 +626,22 @@ - } - alreadyrunning = span->flags & DAHDI_FLAG_RUNNING; - -- if (!alreadyrunning) { -- span->chans[2]->flags &= ~DAHDI_FLAG_HDLC; -- span->chans[2]->flags |= DAHDI_FLAG_BRIDCHAN; -- -- span->flags |= DAHDI_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 &= ~DAHDI_FLAG_HDLC; -+ span->chans[2]->flags |= DAHDI_FLAG_BRIDCHAN; -+ -+ span->flags |= DAHDI_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; - } - -@@ -847,17 +671,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; -@@ -897,32 +713,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; -@@ -938,9 +728,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; -@@ -948,6 +738,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; -@@ -961,49 +752,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, IRQF_SHARED, "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 -@@ -1020,11 +801,21 @@ - hfctmp->regs.nt_mode = 0; - } - -- zthfc = kmalloc(sizeof(struct dahdi_hfc),GFP_KERNEL); -+ if(sync_slave&(1<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 dahdi_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; - } -@@ -1050,7 +841,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_get_device(pcivendor, pcidevice, multi_hfc); -@@ -1058,58 +848,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"); - } -@@ -1119,8 +893,11 @@ - #endif - - --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); - - MODULE_DESCRIPTION("HFC-S PCI A Zaptel Driver"); - MODULE_AUTHOR("Klaus-Peter Junghanns "); diff --git a/main/dahdi-linux-vanilla/zaphfc-dahdi-flortz.patch b/main/dahdi-linux-vanilla/zaphfc-dahdi-flortz.patch new file mode 100644 index 0000000000..dc856c97c7 --- /dev/null +++ b/main/dahdi-linux-vanilla/zaphfc-dahdi-flortz.patch @@ -0,0 +1,1232 @@ +Index: dahdi-linux-2.1.0.4/drivers/dahdi/zaphfc.h +=================================================================== +--- dahdi-linux-2.1.0.4.orig/drivers/dahdi/zaphfc.h 2009-03-17 18:13:54.000000000 +0200 ++++ dahdi-linux-2.1.0.4/drivers/dahdi/zaphfc.h 2009-03-17 18:14:44.000000000 +0200 +@@ -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][DAHDI_CHUNKSIZE]; + unsigned char btransbuf[2][DAHDI_CHUNKSIZE]; + unsigned char cardno; ++ int active; ++ struct bch bch; ++ struct dch dch; + struct hfc_card *next; + } hfc_card; + +@@ -285,6 +342,3 @@ + struct hfc_card *card; + } dahdi_hfc; + +-/* tune this */ +-#define hfc_BCHAN_BUFFER 8 +-#define hfc_MAX_CARDS 8 +Index: dahdi-linux-2.1.0.4/drivers/dahdi/zaphfc.c +=================================================================== +--- dahdi-linux-2.1.0.4.orig/drivers/dahdi/zaphfc.c 2009-03-17 18:52:47.000000000 +0200 ++++ dahdi-linux-2.1.0.4/drivers/dahdi/zaphfc.c 2009-03-17 18:53:43.000000000 +0200 +@@ -7,19 +7,21 @@ + * + * Klaus-Peter Junghanns + * ++ * Copyright (C) 2004, 2005, 2006 Florian Zumbiehl ++ * - 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 + #include +-#ifdef RTAITIMING +-#include +-#include +-#include +-#include +-#endif + #include + #include + #include +@@ -29,6 +31,8 @@ + + #include + ++#define log2(n) ffz(~(n)) ++ + #if CONFIG_PCI + + #define CLKDEL_TE 0x0f /* CLKDEL in TE mode */ +@@ -70,42 +74,31 @@ + static struct hfc_card *hfc_dev_list = NULL; + static int hfc_dev_count = 0; + static int modes = 0; // all TE ++static int sync_slave = 0; // all master ++static int timer_card = 0; ++static int jitterbuffer = 1; + static int debug = 0; + static struct pci_dev *multi_hfc = NULL; + static DEFINE_SPINLOCK(registerlock); + +-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 +@@ -119,8 +112,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; +@@ -130,11 +123,24 @@ + spin_unlock_irqrestore(&hfctmp->lock,flags); + if (hfctmp->ztdev != NULL) { + dahdi_unregister(&hfctmp->ztdev->span); +- kfree(hfctmp->ztdev); ++ vfree(hfctmp->ztdev); + printk(KERN_INFO "unregistered from DAHDI.\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; + +@@ -178,14 +184,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 */ +@@ -197,8 +203,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; +@@ -210,10 +216,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); +@@ -230,368 +234,210 @@ + 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 = DAHDI_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%DAHDI_CHUNKSIZE ++#error hfc_B_FIFO_SIZE is not a multiple of DAHDI_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 = DAHDI_CHUNKSIZE; +- +- if (bytes < DAHDI_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,DAHDI_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 + DAHDI_CHUNKSIZE) { +- /* if the system is too slow to handle it, we will have to drop it all (except 1 DAHDI chunk) */ +- drop = bytes - DAHDI_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%=DAHDI_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<=DAHDI_CHUNKSIZE*jitterbuffer&&chtmp->tx.c[1].filled<=DAHDI_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) { +- dahdi_ec_chunk(&hfctmp->ztdev->chans[0], hfctmp->ztdev->chans[0].readchunk, hfctmp->ztdev->chans[0].writechunk); +- } else { +- dahdi_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,DAHDI_CHUNKSIZE); ++ hfc_bch_inc_z(chtmp->tx.z1,DAHDI_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>=DAHDI_CHUNKSIZE&&chtmp->rx.c[1].filled>=DAHDI_CHUNKSIZE){ ++ if((chtmp->rx.c[0].filled>=DAHDI_CHUNKSIZE*(jitterbuffer+2)&&chtmp->rx.c[1].filled>=DAHDI_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%DAHDI_CHUNKSIZE-DAHDI_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),DAHDI_CHUNKSIZE); ++ dahdi_ec_chunk(&hfctmp->ztdev->chans[x],hfctmp->ztdev->chans[x].readchunk,hfctmp->ztdev->chans[x].writechunk); ++ } ++ hfc_bch_inc_z(chtmp->rx.z2,DAHDI_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; xdch; ++ 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;xztdev->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))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 DAHDI buffer +- we'll call dahdi_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 + DAHDI_IRQ_HANDLER(hfc_interrupt) { + struct hfc_card *hfctmp = dev_id; +- unsigned long flags = 0; +- unsigned char stat; +-#else +-static void hfc_service(struct hfc_card *hfctmp) { +-#endif ++ struct hfc_card *hfctmp2; + struct dahdi_hfc *zthfc; +- unsigned char s1, s2, l1state; ++ unsigned char stat, s1, s2, l1state; ++ unsigned long flags = 0; ++ unsigned long flags2 = 0; + int x; + + if (!hfctmp) { +-#ifndef RTAITIMING +- return IRQ_NONE; +-#else +- /* rtai */ +- return; +-#endif ++ return IRQ_NONE; + } + + if (!hfctmp->pci_io) { + printk(KERN_WARNING "%s: IO-mem disabled, cannot handle interrupt\n", + __FUNCTION__); +-#ifndef RTAITIMING + return IRQ_NONE; +-#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); + return IRQ_NONE; + } +-#endif + + s1 = hfc_inb(hfctmp, hfc_INT_S1); + s2 = hfc_inb(hfctmp, hfc_INT_S2); +@@ -611,18 +457,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); +@@ -636,18 +474,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); +@@ -657,7 +487,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"); + } +@@ -678,14 +508,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) +@@ -693,32 +519,31 @@ + 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 DAHDI timing :) +-#endif +- hfctmp->ticks = 0; +- +- if (hfctmp->ztdev->span.flags & DAHDI_FLAG_RUNNING) { ++ 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 & DAHDI_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; + + dahdi_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); +@@ -743,17 +568,16 @@ + if (hfctmp->ztdev->span.flags & DAHDI_FLAG_RUNNING) { + dahdi_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); +- return IRQ_RETVAL(1); +-#endif ++ return IRQ_RETVAL(1); + } + + +@@ -802,22 +626,22 @@ + } + alreadyrunning = span->flags & DAHDI_FLAG_RUNNING; + +- if (!alreadyrunning) { +- span->chans[2]->flags &= ~DAHDI_FLAG_HDLC; +- span->chans[2]->flags |= DAHDI_FLAG_BRIDCHAN; +- +- span->flags |= DAHDI_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 &= ~DAHDI_FLAG_HDLC; ++ span->chans[2]->flags |= DAHDI_FLAG_BRIDCHAN; ++ ++ span->flags |= DAHDI_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; + } + +@@ -847,17 +671,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; +@@ -897,32 +713,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; +@@ -938,9 +728,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; +@@ -948,6 +738,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; +@@ -961,49 +752,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, IRQF_SHARED, "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 +@@ -1020,11 +801,21 @@ + hfctmp->regs.nt_mode = 0; + } + +- zthfc = kmalloc(sizeof(struct dahdi_hfc),GFP_KERNEL); ++ if(sync_slave&(1<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 dahdi_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; + } +@@ -1050,7 +841,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_get_device(pcivendor, pcidevice, multi_hfc); +@@ -1058,58 +848,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"); + } +@@ -1119,8 +893,11 @@ + #endif + + +-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); + + MODULE_DESCRIPTION("HFC-S PCI A Zaptel Driver"); + MODULE_AUTHOR("Klaus-Peter Junghanns "); -- cgit v1.2.3