diff options
author | William Pitcock <nenolod@dereferenced.org> | 2017-04-27 04:57:01 +0000 |
---|---|---|
committer | William Pitcock <nenolod@dereferenced.org> | 2017-04-27 05:46:22 +0000 |
commit | 621380ffefe7bf0ed9eac9e730b8f36ed4cd0167 (patch) | |
tree | e43f5fd6cf83f8493462e7e6ad67d3ed728db134 /main | |
parent | 8771699b5999395fca175dbf93c0e99679a2509c (diff) | |
download | aports-621380ffefe7bf0ed9eac9e730b8f36ed4cd0167.tar.bz2 aports-621380ffefe7bf0ed9eac9e730b8f36ed4cd0167.tar.xz |
main/dadhi-linux-hardened: rename from dadhi-linux-grsec, provide dadhi-linux-grsec
Diffstat (limited to 'main')
-rw-r--r-- | main/dahdi-linux-hardened/APKBUILD | 106 | ||||
-rw-r--r-- | main/dahdi-linux-hardened/constify.patch | 22 | ||||
-rw-r--r-- | main/dahdi-linux-hardened/dahdi-2.5.0-bri-fixes.patch | 327 | ||||
-rw-r--r-- | main/dahdi-linux-hardened/dahdi-bri_dchan.patch | 167 | ||||
-rw-r--r-- | main/dahdi-linux-hardened/dahdi-depmod.patch | 22 | ||||
-rw-r--r-- | main/dahdi-linux-hardened/dahdi-zaphfc.patch | 1429 | ||||
-rw-r--r-- | main/dahdi-linux-hardened/linux-3.13.patch | 12 | ||||
-rw-r--r-- | main/dahdi-linux-hardened/linux-4.4.patch | 10 | ||||
-rw-r--r-- | main/dahdi-linux-hardened/zaphfc-dahdi-2.4.0.patch | 58 | ||||
-rw-r--r-- | main/dahdi-linux-hardened/zaphfc-dahdi-2.5.0.patch | 36 | ||||
-rw-r--r-- | main/dahdi-linux-hardened/zaphfc-dahdi-2.6.0.patch | 58 | ||||
-rw-r--r-- | main/dahdi-linux-hardened/zaphfc-dahdi-2.7.0.patch | 32 | ||||
-rw-r--r-- | main/dahdi-linux-hardened/zaphfc-dahdi-flortz.diff | 1232 |
13 files changed, 3511 insertions, 0 deletions
diff --git a/main/dahdi-linux-hardened/APKBUILD b/main/dahdi-linux-hardened/APKBUILD new file mode 100644 index 0000000000..c9ed2a3fd3 --- /dev/null +++ b/main/dahdi-linux-hardened/APKBUILD @@ -0,0 +1,106 @@ +# Contributor: Timo Teras <timo.teras@iki.fi> +# Maintainer: Timo Teras <timo.teras@iki.fi> + +_flavor=hardened +_kpkg=linux-$_flavor +_kver=4.9.24 +_kpkgrel=1 +_mypkgrel=0 + +_kpkgver="$_kver-r$_kpkgrel" +_abi_release=${_kver}-${_kpkgrel}-${_flavor} +_realname=dahdi-linux + +pkgname=${_realname}-${_flavor} +pkgver=$_kver +# when chaning _dahdiver we *must* bump _mypkgrel +_dahdiver=2.11.1 +pkgrel=$(( $_kpkgrel + $_mypkgrel )) +pkgdesc="Digium Asterisk Hardware Device Interface drivers $_dahdiver" +url="http://www.asterisk.org" +arch="x86 x86_64" +license="GPL" +depends="dahdi-linux linux-${_flavor}=${_kpkgver}" +# we need wget and tar because make install downloads firmware and uses fancy +# options for tar and wget. +makedepends="linux-${_flavor}-dev=${_kpkgver} wget tar perl" +install= +subpackages="$pkgname-dev" +provides="${_realname}-grsec=${pkgver}-r${pkgrel}" +source="http://downloads.digium.com/pub/telephony/dahdi-linux/releases/${_realname}-$_dahdiver.tar.gz + dahdi-depmod.patch + dahdi-bri_dchan.patch + dahdi-zaphfc.patch + zaphfc-dahdi-flortz.diff + zaphfc-dahdi-2.4.0.patch + zaphfc-dahdi-2.5.0.patch + zaphfc-dahdi-2.6.0.patch + zaphfc-dahdi-2.7.0.patch + constify.patch + linux-3.13.patch + linux-4.4.patch + " + +prepare() { + cd "$srcdir/$_realname-$_dahdiver" + # verify the kernel version + ( + + if [ -f "$startdir"/../linux-${_flavor}/APKBUILD ]; then + . "$startdir"/../linux-${_flavor}/APKBUILD + if [ "$_kver" != "$pkgver" ]; then + die "dahdi-linux-grsec: please update _kver to $pkgver" + fi + if [ "$_kpkgrel" != "$pkgrel" ]; then + die "dahdi-linux-grsec: please update _kpkgrel to $pkgrel" + fi + fi + ) || return 1 + + for i in $source; do + case $i in + *.patch|*.diff) + msg "Applying $i" + patch -p1 -i "$srcdir"/$i || return 1 + ;; + esac + done +} + +build() { + cd "$srcdir/$_realname-$_dahdiver" + make KVERS="${_abi_release}" DYNFS="yes" MODULES_EXTRA="zaphfc" \ + || return 1 +} + +package() { + cd "$srcdir/$_realname-$_dahdiver" + make KVERS="${_abi_release}" DYNFS="yes" MODULES_EXTRA="zaphfc" \ + DESTDIR="$pkgdir" install-modules || return 1 + rm -rf "$pkgdir"/lib/firmware "$pkgdir"/usr/lib/hotplug/firmware \ + "$pkgdir"/usr/include +} + +# since we sourced the APKBUILD above we got the dev() function there to +# so we override it again. +depends_dev="dahdi-linux-dev" +dev() { + default_dev + local dir="$subpkgdir"/usr/src/dahdi-headers-${_abi_release} + install -D "$srcdir"/$_realname-$_dahdiver/drivers/dahdi/Module.symvers \ + "$dir"/drivers/dahdi/Module.symvers + ln -s /usr/include "$dir"/include +} + +sha512sums="db15d9237f157b5349de8f4cdb45573ed42e1dd25c83f900835c7e15637a19e1e95c7c990dc786c1e3f37f32419f3d009e179d27b5d16421789ff9bc76f54224 dahdi-linux-2.11.1.tar.gz +aba01eb90d9db1c595ff22078c76aadb20900486b5794d38b7ee61fa30d2fb51be318a4d059246017640447aee03fb09bb5514c818e3caa1cd98e331ec065173 dahdi-depmod.patch +fa2fa9e96eefc0f31a1a4a8f8f44e77936f6da0d7b74fe3c3d1f0de085621744ae4367932ac97a10b7f96b7d0954843b0bfe07a251b85434079cc6da29e243ba dahdi-bri_dchan.patch +8ef31c9723237da83954832df5aee1f5daa23f8fefe07a1a191a2c5da2c2308001d68cee83500f7ef43166bfc0d65552b0ca5362789c5c82a7217e09362fd5fe dahdi-zaphfc.patch +f18043fd18a05be7e49daa9d8c96c8a8c45936b14e82e30523e4d88b1620a73147f765d24d2038c4ec0855901e36e8e2b188d596f94437dfb80f6d76ab699d9d zaphfc-dahdi-flortz.diff +8068fcbba81b819bbd14a1a324457d0febd5350d16c6443be035c50f7759010376bd92d3c7ea69b47309e02603e587387b643f64663652e162853515371a6da5 zaphfc-dahdi-2.4.0.patch +95811d56f5567bbab1e6fac89fdc7a4d78252a54a416e884903ae2709f8922f5cd02c492de0bad5c35fdfd52250ec231ed11457e36ba33f8747c3226491882de zaphfc-dahdi-2.5.0.patch +7533c640817f71789c922bb9a5a3b6132b5b47958770929b1c9a50a1e2e6de914e278f466a85ef99759e291e5907c56d60926c74075f4e731a9910a46c1be3ea zaphfc-dahdi-2.6.0.patch +daca74da31c655265164a854987d45ca5ee3af1defbe2d49a9f1a70a48a43dc2bc3ceba724781ae29e3a9078b827f641d2e29809fb25101986f2f69c767d1382 zaphfc-dahdi-2.7.0.patch +c247ce53dd0c9f069d4881c89bd0dc1a816562761874731924af482c40736d6604b360b26642ba5d5d86208c8231de703aa0d858e40911cb0dda46c8fabfd19e constify.patch +dfc2b0357dc3d2a37c45f1fcc503009cf35e99c8b174d0dd7c91ac4c2c9bb3428f9a19a3f264446069fd751441833f43e11b3b55a060865c6daca9bef74008be linux-3.13.patch +18cc299c9b9ab05b93769c0aa68595d3b3b640b97c6ee546b9cbe551f08679557c7e2a5a8255577ab6ae7036c2210550b45066b03d04ebbe7adad1a59aba5866 linux-4.4.patch" diff --git a/main/dahdi-linux-hardened/constify.patch b/main/dahdi-linux-hardened/constify.patch new file mode 100644 index 0000000000..6741522f23 --- /dev/null +++ b/main/dahdi-linux-hardened/constify.patch @@ -0,0 +1,22 @@ +--- ./drivers/dahdi/voicebus/voicebus.h.orig ++++ ./drivers/dahdi/voicebus/voicebus.h +@@ -89,7 +89,7 @@ + void (*handle_receive)(struct voicebus *vb, struct list_head *buffers); + void (*handle_transmit)(struct voicebus *vb, struct list_head *buffers); + void (*handle_error)(struct voicebus *vb); +-}; ++} __no_const; + + /** + * struct voicebus_descriptor_list - A single descriptor list. +--- ./drivers/dahdi/wctc4xxp/base.c.orig ++++ ./drivers/dahdi/wctc4xxp/base.c +@@ -3193,7 +3193,7 @@ + return ret; + } + +-static void wctc4xxp_setup_file_operations(struct file_operations *fops) ++static void wctc4xxp_setup_file_operations(file_operations_no_const *fops) + { + fops->owner = THIS_MODULE; + fops->read = wctc4xxp_read; diff --git a/main/dahdi-linux-hardened/dahdi-2.5.0-bri-fixes.patch b/main/dahdi-linux-hardened/dahdi-2.5.0-bri-fixes.patch new file mode 100644 index 0000000000..01dcf646fb --- /dev/null +++ b/main/dahdi-linux-hardened/dahdi-2.5.0-bri-fixes.patch @@ -0,0 +1,327 @@ +Index: dahdi-linux-2.5.0/drivers/dahdi/xpp/card_bri.c +=================================================================== +--- dahdi-linux-2.5.0.orig/drivers/dahdi/xpp/card_bri.c 2011-08-15 14:42:29.000000000 +0300 ++++ dahdi-linux-2.5.0/drivers/dahdi/xpp/card_bri.c 2011-08-15 14:51:37.000000000 +0300 +@@ -274,7 +274,6 @@ + int frame_begin; + + priv = xpd->priv; +- BUG_ON(!priv); + if(transmit) { + direction = "TX"; + frame_begin = priv->txframe_begin; +@@ -312,9 +311,7 @@ + { + struct BRI_priv_data *priv; + +- BUG_ON(!xpd); + priv = xpd->priv; +- BUG_ON(!priv); + if(priv->dchan_alive == up) + return; + if(up) { +@@ -332,9 +329,7 @@ + { + struct BRI_priv_data *priv; + +- BUG_ON(!xpd); + priv = xpd->priv; +- BUG_ON(!priv); + if(priv->layer1_up == up) + return; + priv->layer1_up = up; +@@ -348,9 +343,7 @@ + struct BRI_priv_data *priv; + byte curr_state; + +- BUG_ON(!xpd); + priv = xpd->priv; +- BUG_ON(!priv); + curr_state = priv->state_register.bits.v_su_sta; + XPD_DBG(SIGNAL, xpd, "%s\n", (on)?"ON":"OFF"); + if(on) { +@@ -391,9 +384,7 @@ + struct BRI_priv_data *priv; + byte curr_state; + +- BUG_ON(!xpd); + priv = xpd->priv; +- BUG_ON(!priv); + curr_state = priv->state_register.bits.v_su_sta; + XPD_DBG(SIGNAL, xpd, "%s\n", (on)?"ON":"OFF"); + if(on) { +@@ -443,7 +434,6 @@ + struct BRI_priv_data *priv; + + priv = xpd->priv; +- BUG_ON(!priv); + #ifdef CONFIG_DAHDI_BRI_DCHANS + if(debug & DBG_COMMANDS) + dump_hex_buf(xpd, "D-Chan(abort) RX: dchan_rbuf", +@@ -460,7 +450,6 @@ + byte status; + + priv = xpd->priv; +- BUG_ON(!priv); + #ifdef CONFIG_DAHDI_BRI_DCHANS + if(priv->dchan_r_idx < 4) { + XPD_NOTICE(xpd, "D-Chan RX short frame (dchan_r_idx=%d)\n", +@@ -503,7 +492,6 @@ + int idx; + + priv = xpd->priv; +- BUG_ON(!priv); + dchan_buf = dchan->readchunk; + idx = priv->dchan_r_idx; + if(idx + len >= DCHAN_BUFSIZE) { +@@ -527,7 +515,6 @@ + struct BRI_priv_data *priv; + + priv = xpd->priv; +- BUG_ON(!priv); + #ifdef CONFIG_DAHDI_BRI_DCHANS + dchan->bytes2receive = priv->dchan_r_idx - 1; + dchan->eofrx = 1; +@@ -556,10 +543,7 @@ + return 0; + if(!SPAN_REGISTERED(xpd)) /* Nowhere to copy data */ + return 0; +- BUG_ON(!xpd); + priv = xpd->priv; +- BUG_ON(!priv); +- xbus = xpd->xbus; + dchan = XPD_CHAN(xpd, 2); + if(!IS_OFFHOOK(xpd, 2)) { /* D-chan is used? */ + static int rate_limit; +@@ -629,9 +613,7 @@ + return 0; + if(!SPAN_REGISTERED(xpd)) /* Nowhere to copy data */ + return 0; +- BUG_ON(!xpd); + priv = xpd->priv; +- BUG_ON(!priv); + dchan = XPD_CHAN(xpd, 2); + if(!IS_OFFHOOK(xpd, 2)) { /* D-chan is used? */ + static int rate_limit; +@@ -677,7 +659,6 @@ + struct BRI_priv_data *priv; + + priv = xpd->priv; +- BUG_ON(!priv); + dchan = XPD_CHAN(xpd, 2); + if (dchan == chan) { + atomic_inc(&priv->hdlc_pending); +@@ -716,7 +697,6 @@ + int ret; + + priv = xpd->priv; +- BUG_ON(!priv); + #ifndef CONFIG_DAHDI_BRI_DCHANS + if(atomic_read(&priv->hdlc_pending) == 0) + return 0; +@@ -769,7 +749,6 @@ + { + struct BRI_priv_data *priv; + +- BUG_ON(!xpd); + priv = xpd->priv; + XPD_DBG(PROC, xpd, "\n"); + #ifdef CONFIG_PROC_FS +@@ -784,7 +763,6 @@ + { + struct BRI_priv_data *priv; + +- BUG_ON(!xpd); + priv = xpd->priv; + XPD_DBG(PROC, xpd, "\n"); + #ifdef CONFIG_PROC_FS +@@ -828,7 +806,6 @@ + { + struct BRI_priv_data *priv; + +- BUG_ON(!xpd); + XPD_DBG(GENERAL, xpd, "\n"); + priv = xpd->priv; + DO_LED(xpd, GREEN_LED, BRI_LED_OFF); +@@ -841,7 +818,6 @@ + + static int BRI_card_remove(xbus_t *xbus, xpd_t *xpd) + { +- BUG_ON(!xpd); + XPD_DBG(GENERAL, xpd, "\n"); + bri_proc_remove(xbus, xpd); + return 0; +@@ -877,10 +853,8 @@ + struct BRI_priv_data *priv; + int i; + +- BUG_ON(!xpd); + xbus = xpd->xbus; + priv = xpd->priv; +- BUG_ON(!xbus); + XPD_DBG(GENERAL, xpd, "%s\n", (on)?"on":"off"); + if(!on) { + /* Nothing to do yet */ +@@ -927,11 +901,6 @@ + + static int BRI_card_dahdi_postregistration(xpd_t *xpd, bool on) + { +- xbus_t *xbus; +- +- BUG_ON(!xpd); +- xbus = xpd->xbus; +- BUG_ON(!xbus); + XPD_DBG(GENERAL, xpd, "%s\n", (on)?"on":"off"); + return(0); + } +@@ -956,7 +925,6 @@ + int other_led; + int mod; + +- BUG_ON(!xpd); + if(IS_NT(xpd)) { + which_led = RED_LED; + other_led = GREEN_LED; +@@ -965,7 +933,6 @@ + other_led = RED_LED; + } + priv = xpd->priv; +- BUG_ON(!priv); + timer_count = xpd->timer_count; + if(xpd->blink_mode) { + if((timer_count % DEFAULT_LED_PERIOD) == 0) { +@@ -1014,9 +981,7 @@ + { + struct BRI_priv_data *priv; + +- BUG_ON(!xpd); + priv = xpd->priv; +- BUG_ON(!priv); + if(IS_NT(xpd)) { + if (priv->t1 > HFC_TIMER_OFF) { + if (--priv->t1 == 0) { +@@ -1053,9 +1018,7 @@ + { + struct BRI_priv_data *priv; + +- BUG_ON(!xpd); + priv = xpd->priv; +- BUG_ON(!priv); + if(!priv->initialized || !xbus->self_ticking) + return 0; + if(poll_interval != 0 && (priv->tick_counter % poll_interval) == 0) { +@@ -1111,7 +1074,6 @@ + + static int BRI_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long arg) + { +- BUG_ON(!xpd); + if(!XBUS_IS(xpd->xbus, READY)) + return -ENODEV; + switch (cmd) { +@@ -1131,7 +1093,6 @@ + + static int BRI_card_open(xpd_t *xpd, lineno_t pos) + { +- BUG_ON(!xpd); + if(pos == 2) { + LINE_DBG(SIGNAL, xpd, pos, "OFFHOOK the whole span\n"); + BIT_SET(PHONEDEV(xpd).offhook_state, 0); +@@ -1230,12 +1191,8 @@ + { + struct phonedev *phonedev = container_of(span, struct phonedev, span); + xpd_t *xpd = container_of(phonedev, struct xpd, phonedev); +- struct BRI_priv_data *priv; + struct dahdi_chan *dchan; + +- BUG_ON(!xpd); +- priv = xpd->priv; +- BUG_ON(!priv); + if(!XBUS_IS(xpd->xbus, READY)) { + XPD_DBG(GENERAL, xpd, "Startup called by dahdi. No Hardware. Ignored\n"); + return -ENODEV; +@@ -1267,11 +1224,7 @@ + { + struct phonedev *phonedev = container_of(span, struct phonedev, span); + xpd_t *xpd = container_of(phonedev, struct xpd, phonedev); +- struct BRI_priv_data *priv; + +- BUG_ON(!xpd); +- priv = xpd->priv; +- BUG_ON(!priv); + if(!XBUS_IS(xpd->xbus, READY)) { + XPD_DBG(GENERAL, xpd, "Shutdown called by dahdi. No Hardware. Ignored\n"); + return -ENODEV; +@@ -1292,7 +1245,6 @@ + xpd_t *main_xpd; + unsigned long flags; + +- BUG_ON(!xpd); + main_xpd = xpd_byaddr(xpd->xbus, xpd->addr.unit, 0); + if(!main_xpd) { + XPD_DBG(DEVICES, xpd, "Unit 0 is already gone. Ignore request\n"); +@@ -1350,8 +1302,6 @@ + xpp_line_t wanted_lines; + + +- BUG_ON(!xpd); +- BUG_ON(!pack); + pcm = RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, pcm); + for(subunit = 0; subunit < MAX_SUBUNIT; subunit++) { + xpd_t *tmp_xpd; +@@ -1435,12 +1385,8 @@ + + static int BRI_echocancel_setmask(xpd_t *xpd, xpp_line_t ec_mask) + { +- struct BRI_priv_data *priv; + int i; + +- BUG_ON(!xpd); +- priv = xpd->priv; +- BUG_ON(!priv); + XPD_DBG(GENERAL, xpd, "0x%8X\n", ec_mask); + if (!ECHOOPS(xpd->xbus)) { + XPD_DBG(GENERAL, xpd, +@@ -1466,9 +1412,7 @@ + struct bri_leds *bri_leds; + struct BRI_priv_data *priv; + +- BUG_ON(!xbus); + priv = xpd->priv; +- BUG_ON(!priv); + XPD_DBG(LEDS, xpd, "%s -> %d\n", + (which_led)?"RED":"GREEN", + to_led_state); +@@ -1507,9 +1451,7 @@ + struct BRI_priv_data *priv; + su_rd_sta_t new_state; + +- BUG_ON(!xpd); + priv = xpd->priv; +- BUG_ON(!priv); + if(!priv->initialized) { + XPD_ERR(xpd, "%s called on uninitialized AB\n", __FUNCTION__); + return; +@@ -1621,7 +1563,6 @@ + } + spin_lock_irqsave(&xpd->lock, flags); + priv = xpd->priv; +- BUG_ON(!priv); + if(REG_FIELD(info, do_subreg)) { + XPD_DBG(REGS, xpd, "RI %02X %02X %02X\n", + REG_FIELD(info, regnum), REG_FIELD(info, subreg), REG_FIELD(info, data_low)); +@@ -1665,7 +1606,6 @@ + { + struct BRI_priv_data *priv; + +- BUG_ON(!xpd); + priv = xpd->priv; + XPD_DBG(GENERAL, xpd, "%s\n", (on)?"ON":"OFF"); + if(on) { +@@ -1745,7 +1685,6 @@ + return -ENODEV; + spin_lock_irqsave(&xpd->lock, flags); + priv = xpd->priv; +- BUG_ON(!priv); + len += sprintf(page + len, "%05d Layer 1: ", priv->poll_counter); + if(priv->reg30_good) { + len += sprintf(page + len, "%-5s ", (priv->layer1_up) ? "UP" : "DOWN"); diff --git a/main/dahdi-linux-hardened/dahdi-bri_dchan.patch b/main/dahdi-linux-hardened/dahdi-bri_dchan.patch new file mode 100644 index 0000000000..8d2ba97fd1 --- /dev/null +++ b/main/dahdi-linux-hardened/dahdi-bri_dchan.patch @@ -0,0 +1,167 @@ +# Translate the D channels to a standard channel data. +# The HFC chipset provides us the D channel as data, but +# Zaptel expects it as a standard channel with 1000 samples +# per second. + +Index: dahdi-linux-2.5.0/include/dahdi/kernel.h +=================================================================== +--- dahdi-linux-2.5.0.orig/include/dahdi/kernel.h 2011-06-29 18:32:40.000000000 +0300 ++++ dahdi-linux-2.5.0/include/dahdi/kernel.h 2011-08-15 14:14:26.000000000 +0300 +@@ -413,6 +413,13 @@ + int statcount; + int lastnumbufs; + #endif ++#ifdef CONFIG_DAHDI_BRI_DCHANS ++ int bytes2receive; ++ int maxbytes2transmit; /* size of the tx buffer in the card driver */ ++ int bytes2transmit; ++ int eofrx; ++ int eoftx; ++#endif + spinlock_t lock; + char name[40]; + /* Specified by DAHDI */ +@@ -723,6 +730,9 @@ + DAHDI_FLAGBIT_TXUNDERRUN = 22, /*!< Transmit underrun condition */ + DAHDI_FLAGBIT_RXOVERRUN = 23, /*!< Receive overrun condition */ + DAHDI_FLAGBIT_DEVFILE = 25, /*!< Channel has a sysfs dev file */ ++#if defined(CONFIG_DAHDI_BRI_DCHANS) ++ DAHDI_FLAGBIT_BRIDCHAN = 26, /*!< hardhdlc-like handling of the D channel */ ++#endif + }; + + #ifdef CONFIG_DAHDI_NET +@@ -789,6 +799,7 @@ + #define DAHDI_FLAG_BUFEVENTS DAHDI_FLAG(BUFEVENTS) + #define DAHDI_FLAG_TXUNDERRUN DAHDI_FLAG(TXUNDERRUN) + #define DAHDI_FLAG_RXOVERRUN DAHDI_FLAG(RXOVERRUN) ++#define DAHDI_FLAG_BRIDCHAN DAHDI_FLAG(BRIDCHAN) + + struct file; + +Index: dahdi-linux-2.5.0/include/dahdi/dahdi_config.h +=================================================================== +--- dahdi-linux-2.5.0.orig/include/dahdi/dahdi_config.h 2011-01-05 17:52:03.000000000 +0200 ++++ dahdi-linux-2.5.0/include/dahdi/dahdi_config.h 2011-08-15 14:13:01.000000000 +0300 +@@ -195,4 +195,10 @@ + */ + /* #define CONFIG_DAHDI_MIRROR */ + ++/* ++ * Uncomment the following for BRI D channels ++ * ++ */ ++#define CONFIG_DAHDI_BRI_DCHANS ++ + #endif +Index: dahdi-linux-2.5.0/drivers/dahdi/dahdi-base.c +=================================================================== +--- dahdi-linux-2.5.0.orig/drivers/dahdi/dahdi-base.c 2011-07-21 19:26:31.000000000 +0300 ++++ dahdi-linux-2.5.0/drivers/dahdi/dahdi-base.c 2011-08-15 14:13:01.000000000 +0300 +@@ -7224,11 +7224,40 @@ + *(txb++) = fasthdlc_tx_run_nocheck(&ms->txhdlc); + } + bytes -= left; ++#ifdef CONFIG_DAHDI_BRI_DCHANS ++ } else if (test_bit(DAHDI_FLAGBIT_BRIDCHAN, &ms->flags)) { ++ /* ++ * Let's get this right, we want to transmit complete frames only. ++ * The card driver will do the dirty HDLC work for us. ++ * txb (transmit buffer) is supposed to be big enough to store one frame ++ * we will make this as big as the D fifo (1KB or 2KB) ++ */ ++ ++ /* there are 'left' bytes in the user buffer left to transmit */ ++ left = ms->writen[ms->outwritebuf] - ms->writeidx[ms->outwritebuf] - 2; ++ if (left > ms->maxbytes2transmit) { ++ memcpy(txb, buf + ms->writeidx[ms->outwritebuf], ms->maxbytes2transmit); ++ ms->writeidx[ms->outwritebuf] += ms->maxbytes2transmit; ++ txb += ms->maxbytes2transmit; ++ ms->bytes2transmit = ms->maxbytes2transmit; ++ ms->eoftx = 0; ++ } else { ++ memcpy(txb, buf + ms->writeidx[ms->outwritebuf], left); ++ ms->writeidx[ms->outwritebuf] += left + 2; ++ txb += left + 2; ++ ms->bytes2transmit = left; ++ ms->eoftx = 1; ++ } ++ bytes = 0; ++#endif + } else { + memcpy(txb, buf + ms->writeidx[ms->outwritebuf], left); + ms->writeidx[ms->outwritebuf]+=left; + txb += left; + bytes -= left; ++#if defined(CONFIG_DAHDI_BRI_DCHANS) ++ ms->bytes2transmit=DAHDI_CHUNKSIZE; ++#endif + } + /* Check buffer status */ + if (ms->writeidx[ms->outwritebuf] >= ms->writen[ms->outwritebuf]) { +@@ -7285,6 +7314,17 @@ + /* Transmit a flag if this is an HDLC channel */ + if (ms->flags & DAHDI_FLAG_HDLC) + fasthdlc_tx_frame_nocheck(&ms->txhdlc); ++#if defined(CONFIG_DAHDI_BRI_DCHANS) ++ if (test_bit(DAHDI_FLAGBIT_BRIDCHAN, &ms->flags)) { ++ // if (ms->bytes2transmit > 0) { ++ // txb += 2; ++ // ms->bytes2transmit -= 2; ++ bytes=0; ++ ms->eoftx = 1; ++// printk(KERN_CRIT "zaptel EOF(%d) bytes2transmit %d\n",ms->eoftx,ms->bytes2transmit); ++ // } ++ } ++#endif + #ifdef CONFIG_DAHDI_NET + if (dahdi_have_netdev(ms)) + netif_wake_queue(chan_to_netdev(ms)); +@@ -7346,6 +7386,12 @@ + } + needtxunderrun += bytes; + bytes = 0; ++#if defined(CONFIG_DAHDI_BRI_DCHANS) ++ } else if (test_bit(DAHDI_FLAGBIT_BRIDCHAN, &ms->flags)) { ++ ms->bytes2transmit = 0; ++ ms->eoftx = 0; ++ bytes = 0; ++#endif + } else { + memset(txb, DAHDI_LIN2X(0, ms), bytes); /* Lastly we use silence on telephony channels */ + needtxunderrun += bytes; +@@ -8267,6 +8313,14 @@ + int res; + int left, x; + ++#if defined(CONFIG_DAHDI_BRI_DCHANS) ++ if (test_bit(DAHDI_FLAGBIT_BRIDCHAN, &ms->flags)) { ++ bytes = ms->bytes2receive; ++ if (bytes < 1) return; ++// printk(KERN_CRIT "bytes2receive %d\n",ms->bytes2receive); ++ } ++#endif ++ + while(bytes) { + #if defined(CONFIG_DAHDI_NET) || defined(CONFIG_DAHDI_PPP) + skb = NULL; +@@ -8324,6 +8378,19 @@ + } + } + } ++#ifdef CONFIG_DAHDI_BRI_DCHANS ++ } else if (test_bit(DAHDI_FLAGBIT_BRIDCHAN, &ms->flags)) { ++ memcpy(buf + ms->readidx[ms->inreadbuf], rxb, left); ++ rxb += left; ++ ms->readidx[ms->inreadbuf] += left; ++ bytes -= left; ++ if (ms->eofrx == 1) { ++ eof=1; ++ } ++// printk(KERN_CRIT "receiving %d bytes\n",ms->bytes2receive); ++ ms->bytes2receive = 0; ++ ms->eofrx = 0; ++#endif + } else { + /* Not HDLC */ + memcpy(buf + ms->readidx[ms->inreadbuf], rxb, left); diff --git a/main/dahdi-linux-hardened/dahdi-depmod.patch b/main/dahdi-linux-hardened/dahdi-depmod.patch new file mode 100644 index 0000000000..289aad403b --- /dev/null +++ b/main/dahdi-linux-hardened/dahdi-depmod.patch @@ -0,0 +1,22 @@ +Index: dahdi-linux-2.0.0-rc4/Makefile +=================================================================== +--- dahdi-linux-2.0.0-rc4.orig/Makefile 2008-09-09 14:07:23.000000000 +0300 ++++ dahdi-linux-2.0.0-rc4/Makefile 2008-09-09 14:12:31.000000000 +0300 +@@ -190,7 +190,7 @@ + build_tools/uninstall-modules dahdi $(KVERS) + endif + $(KMAKE) INSTALL_MOD_PATH=$(DESTDIR) INSTALL_MOD_DIR=dahdi modules_install +- [ `id -u` = 0 ] && /sbin/depmod -a $(KVERS) || : ++ [ -z "$(DESTDIR)" -a `id -u` = 0 ] && /sbin/depmod -a $(KVERS) || : + + uninstall-modules: + ifdef DESTDIR +@@ -203,7 +203,7 @@ + rm -rf /lib/modules/$(KVERS)/dahdi; \ + echo "done."; \ + fi +- [ `id -u` = 0 ] && /sbin/depmod -a $(KVERS) || : ++ [ -z "$(DESTDIR)" -a `id -u` = 0 ] && /sbin/depmod -a $(KVERS) || : + endif + + update: diff --git a/main/dahdi-linux-hardened/dahdi-zaphfc.patch b/main/dahdi-linux-hardened/dahdi-zaphfc.patch new file mode 100644 index 0000000000..931c5b5cf6 --- /dev/null +++ b/main/dahdi-linux-hardened/dahdi-zaphfc.patch @@ -0,0 +1,1429 @@ +Index: dahdi-linux-2.1.0/drivers/dahdi/zaphfc.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ dahdi-linux-2.1.0/drivers/dahdi/zaphfc.c 2008-12-10 12:46:14.000000000 +0200 +@@ -0,0 +1,1129 @@ ++/* ++ * zaphfc.c - Zaptel driver for HFC-S PCI A based ISDN BRI cards ++ * ++ * kernel module inspired by HFC PCI ISDN4Linux and Zaptel drivers ++ * ++ * Copyright (C) 2002, 2003, 2004, 2005 Junghanns.NET GmbH ++ * ++ * Klaus-Peter Junghanns <kpj@junghanns.net> ++ * ++ * This program is free software and may be modified and ++ * distributed under the terms of the GNU 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> ++#include <linux/delay.h> ++#include <dahdi/kernel.h> ++#include "zaphfc.h" ++ ++#include <linux/moduleparam.h> ++ ++#if CONFIG_PCI ++ ++#define CLKDEL_TE 0x0f /* CLKDEL in TE mode */ ++#define CLKDEL_NT 0x6c /* CLKDEL in NT mode */ ++ ++typedef struct { ++ int vendor_id; ++ int device_id; ++ char *vendor_name; ++ char *card_name; ++} PCI_ENTRY; ++ ++static const PCI_ENTRY id_list[] = ++{ ++ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_2BD0, "CCD/Billion/Asuscom", "2BD0"}, ++ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B000, "Billion", "B000"}, ++ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B006, "Billion", "B006"}, ++ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B007, "Billion", "B007"}, ++ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B008, "Billion", "B008"}, ++ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B009, "Billion", "B009"}, ++ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00A, "Billion", "B00A"}, ++ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00B, "Billion", "B00B"}, ++ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00C, "Billion", "B00C"}, ++ {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B100, "Seyeon", "B100"}, ++ {PCI_VENDOR_ID_ABOCOM, PCI_DEVICE_ID_ABOCOM_2BD1, "Abocom/Magitek", "2BD1"}, ++ {PCI_VENDOR_ID_ASUSTEK, PCI_DEVICE_ID_ASUSTEK_0675, "Asuscom/Askey", "675"}, ++ {PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_T_CONCEPT, "German telekom", "T-Concept"}, ++ {PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_A1T, "German telekom", "A1T"}, ++ {PCI_VENDOR_ID_ANIGMA, PCI_DEVICE_ID_ANIGMA_MC145575, "Motorola MC145575", "MC145575"}, ++ {PCI_VENDOR_ID_ZOLTRIX, PCI_DEVICE_ID_ZOLTRIX_2BD0, "Zoltrix", "2BD0"}, ++ {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_IOM2_E,"Digi International", "Digi DataFire Micro V IOM2 (Europe)"}, ++ {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_E,"Digi International", "Digi DataFire Micro V (Europe)"}, ++ {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_IOM2_A,"Digi International", "Digi DataFire Micro V IOM2 (North America)"}, ++ {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_A,"Digi International", "Digi DataFire Micro V (North America)"}, ++ {0x182d, 0x3069,"Sitecom","Isdn 128 PCI"}, ++ {0, 0, NULL, NULL}, ++}; ++ ++static struct hfc_card *hfc_dev_list = NULL; ++static int hfc_dev_count = 0; ++static int modes = 0; // all TE ++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); ++ ++ 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); ++ ++ /* 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); ++ } ++ ++ /* Soft-reset the card */ ++ hfc_outb(hfctmp, hfc_CIRM, hfc_CIRM_RESET); // softreset on ++ ++ 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); ++ ++ hfc_outb(hfctmp,hfc_CIRM,0); // softreset off ++ ++ pci_write_config_word(hfctmp->pcidev, PCI_COMMAND, 0); // disable memio and bustmaster ++ ++ if (hfctmp->fifomem != NULL) { ++ kfree(hfctmp->fifomem); ++ } ++ iounmap((void *) hfctmp->pci_io); ++ hfctmp->pci_io = NULL; ++ if (hfctmp->pcidev != NULL) { ++ pci_disable_device(hfctmp->pcidev); ++ } ++ spin_unlock_irqrestore(&hfctmp->lock,flags); ++ if (hfctmp->ztdev != NULL) { ++ dahdi_unregister(&hfctmp->ztdev->span); ++ kfree(hfctmp->ztdev); ++ printk(KERN_INFO "unregistered from DAHDI.\n"); ++ } ++} ++ ++void hfc_resetCard(struct hfc_card *hfctmp) { ++ unsigned long flags; ++ ++ spin_lock_irqsave(&hfctmp->lock,flags); ++ pci_write_config_word(hfctmp->pcidev, PCI_COMMAND, PCI_COMMAND_MEMORY); // enable memio ++ hfctmp->regs.int_m2 = 0; ++ hfc_outb(hfctmp, hfc_INT_M2, hfctmp->regs.int_m2); ++ ++// printk(KERN_INFO "zaphfc: resetting card.\n"); ++ pci_set_master(hfctmp->pcidev); ++ hfc_outb(hfctmp, hfc_CIRM, hfc_CIRM_RESET); // softreset on ++ spin_unlock_irqrestore(&hfctmp->lock, flags); ++ ++ set_current_state(TASK_UNINTERRUPTIBLE); ++ schedule_timeout((30 * HZ) / 1000); // wait 30 ms ++ hfc_outb(hfctmp, hfc_CIRM, 0); // softreset off ++ ++ set_current_state(TASK_UNINTERRUPTIBLE); ++ schedule_timeout((20 * HZ) / 1000); // wait 20 ms ++ if (hfc_inb(hfctmp,hfc_STATUS) & hfc_STATUS_PCI_PROC) { ++ printk(KERN_WARNING "zaphfc: hfc busy.\n"); ++ } ++ ++// hfctmp->regs.fifo_en = hfc_FIFOEN_D | hfc_FIFOEN_B1 | hfc_FIFOEN_B2; ++// hfctmp->regs.fifo_en = hfc_FIFOEN_D; /* only D fifos enabled */ ++ hfctmp->regs.fifo_en = 0; /* no fifos enabled */ ++ hfc_outb(hfctmp, hfc_FIFO_EN, hfctmp->regs.fifo_en); ++ ++ hfctmp->regs.trm = 2; ++ hfc_outb(hfctmp, hfc_TRM, hfctmp->regs.trm); ++ ++ if (hfctmp->regs.nt_mode == 1) { ++ hfc_outb(hfctmp, hfc_CLKDEL, CLKDEL_NT); /* ST-Bit delay for NT-Mode */ ++ } else { ++ hfc_outb(hfctmp, hfc_CLKDEL, CLKDEL_TE); /* ST-Bit delay for TE-Mode */ ++ } ++ hfctmp->regs.sctrl_e = hfc_SCTRL_E_AUTO_AWAKE; ++ hfc_outb(hfctmp, hfc_SCTRL_E, hfctmp->regs.sctrl_e); /* S/T Auto awake */ ++ hfctmp->regs.bswapped = 0; /* no exchange */ ++ ++ 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; ++ 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 */ ++ hfc_inb(hfctmp, hfc_INT_S1); ++ ++ if (hfctmp->regs.nt_mode == 1) { ++ hfctmp->regs.sctrl = 3 | hfc_SCTRL_NONE_CAP | hfc_SCTRL_MODE_NT; /* set tx_lo mode, error in datasheet ! */ ++ } else { ++ 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_SCTRL, hfctmp->regs.sctrl); ++ hfctmp->regs.sctrl_r = 3; ++ hfc_outb(hfctmp, hfc_SCTRL_R, hfctmp->regs.sctrl_r); ++ ++ hfctmp->regs.connect = 0; ++ hfc_outb(hfctmp, hfc_CONNECT, hfctmp->regs.connect); ++ ++ 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); ++ hfc_inb(hfctmp, hfc_INT_S2); ++} ++ ++void hfc_registerCard(struct hfc_card *hfccard) { ++ spin_lock(®isterlock); ++ if (hfccard != NULL) { ++ hfccard->cardno = hfc_dev_count++; ++ hfccard->next = hfc_dev_list; ++ hfc_dev_list = hfccard; ++ } ++ 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); ++ } ++ } ++ ++ *z1 = newz1; /* send it now */ ++ ++// 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; ++} ++ ++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)); ++ } ++ ++ 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; ++ } ++ ++ /* 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; ++ } ++ ++ ++ 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; ++ } ++ *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 (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); ++ } ++ return; ++} ++ ++ ++static void hfc_dtrans(struct hfc_card *hfctmp) { ++ // we are called with irqs disabled from the irq handler ++ 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; ++ } ++ ++ 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 (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++) { ++ 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; ++ } ++ 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); ++ } ++ } ++ ++ *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; ++ ++ 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; ++ } ++ ++ /* 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 dahdi_hfc *zthfc; ++ unsigned char s1, s2, l1state; ++ int x; ++ ++ if (!hfctmp) { ++#ifndef RTAITIMING ++ return IRQ_NONE; ++#else ++ /* rtai */ ++ return; ++#endif ++ } ++ ++ 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); ++ if (s1 != 0) { ++ if (s1 & hfc_INTS_TIMER) { ++ // timer (bit 7) ++ // printk(KERN_CRIT "timer %d %d %d.\n", stat, s1, s2); ++ } ++ if (s1 & hfc_INTS_L1STATE) { ++ // state machine (bit 6) ++ // printk(KERN_CRIT "zaphfc: layer 1 state machine interrupt\n"); ++ zthfc = hfctmp->ztdev; ++ l1state = hfc_inb(hfctmp,hfc_STATES) & hfc_STATES_STATE_MASK; ++ if (hfctmp->regs.nt_mode == 1) { ++ if (debug) { ++ printk(KERN_CRIT "zaphfc: card %d layer 1 state = G%d\n", hfctmp->cardno, l1state); ++ } ++ 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); ++ } else if (l1state == 3) { ++ // fix to G3 state (see specs) ++ hfc_outb(hfctmp, hfc_STATES, hfc_STATES_LOAD_STATE | 3); ++ } ++ } else { ++ if (debug) { ++ printk(KERN_CRIT "zaphfc: card %d layer 1 state = F%d\n", hfctmp->cardno, l1state); ++ } ++ 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); ++ } ++ } ++ ++ } ++ if (s1 & hfc_INTS_DREC) { ++ // D chan RX (bit 5) ++ hfctmp->regs.int_drec++; ++ // mr. zapata there is something for you! ++ // printk(KERN_CRIT "d chan rx\n"); ++ } ++ if (s1 & hfc_INTS_B2REC) { ++ // B2 chan RX (bit 4) ++ } ++ if (s1 & hfc_INTS_B1REC) { ++ // B1 chan RX (bit 3) ++ } ++ if (s1 & hfc_INTS_DTRANS) { ++ // D chan TX (bit 2) ++// printk(KERN_CRIT "zaphfc: dchan frame transmitted.\n"); ++ } ++ if (s1 & hfc_INTS_B2TRANS) { ++ // B2 chan TX (bit 1) ++ } ++ if (s1 & hfc_INTS_B1TRANS) { ++ // 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"); ++ } ++ if (s2 & hfc_M2_GCI_MON_REC) { ++ // RxR monitor channel (bit 2) ++ } ++ if (s2 & hfc_M2_GCI_I_CHG) { ++ // GCI I-change (bit 1) ++ } ++ if (s2 & hfc_M2_PROC_TRANS) { ++ // 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) { ++ // clear dchan buffer ++ 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_brec(hfctmp,1); ++ hfc_brec(hfctmp,2); ++ if (hfctmp->regs.int_drec > 0) { ++ // dchan data to read ++ hfc_drec(hfctmp); ++ if (hfctmp->ztdev->chans[2].bytes2receive > 0) { ++ if (debug) { ++ printk(KERN_CRIT "zaphfc: card %d RX [ ", hfctmp->cardno); ++ if (hfctmp->ztdev->chans[2].eofrx) { ++ /* dont output CRC == less user confusion */ ++ for (x=0; x < hfctmp->ztdev->chans[2].bytes2receive - 2; x++) { ++ printk("%#2x ", hfctmp->drecbuf[x]); ++ } ++ printk("] %d bytes\n", hfctmp->ztdev->chans[2].bytes2receive - 2); ++ } else { ++ for (x=0; x < hfctmp->ztdev->chans[2].bytes2receive; x++) { ++ printk("%#2x ", hfctmp->drecbuf[x]); ++ } ++ printk("..] %d bytes\n", hfctmp->ztdev->chans[2].bytes2receive); ++ } ++ } ++ } ++ } else { ++ // hmm....ok, let DAHDI receive nothing ++ hfctmp->ztdev->chans[2].bytes2receive = 0; ++ } ++ if (hfctmp->ztdev->span.flags & DAHDI_FLAG_RUNNING) { ++ dahdi_receive(&(hfctmp->ztdev->span)); ++ } ++ ++#ifndef RTAITIMING ++ } ++#endif ++ } ++ ++ } ++#ifndef RTAITIMING ++ spin_unlock_irqrestore(&hfctmp->lock,flags); ++ return IRQ_RETVAL(1); ++#endif ++} ++ ++ ++static int zthfc_open(struct dahdi_chan *chan) { ++ struct dahdi_hfc *zthfc = chan->pvt; ++ struct hfc_card *hfctmp = zthfc->card; ++ ++ if (!hfctmp) { ++ return 0; ++ } ++ try_module_get(THIS_MODULE); ++ return 0; ++} ++ ++static int zthfc_close(struct dahdi_chan *chan) { ++ struct dahdi_hfc *zthfc = chan->pvt; ++ struct hfc_card *hfctmp = zthfc->card; ++ ++ if (!hfctmp) { ++ return 0; ++ } ++ ++ module_put(THIS_MODULE); ++ return 0; ++} ++ ++static int zthfc_rbsbits(struct dahdi_chan *chan, int bits) { ++ return 0; ++} ++ ++static int zthfc_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long data) { ++ switch(cmd) { ++ default: ++ return -ENOTTY; ++ } ++ return 0; ++} ++ ++static int zthfc_startup(struct dahdi_span *span) { ++ struct dahdi_hfc *zthfc = span->pvt; ++ struct hfc_card *hfctmp = zthfc->card; ++ int alreadyrunning; ++ ++ if (hfctmp == NULL) { ++ printk(KERN_INFO "zaphfc: no card for span at startup!\n"); ++ } ++ 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; ++ ++ 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; ++ } ++ ++ // drivers, start engines! ++ hfc_outb(hfctmp, hfc_STATES, hfc_STATES_DO_ACTION | hfc_STATES_ACTIVATE); ++ return 0; ++} ++ ++static int zthfc_shutdown(struct dahdi_span *span) { ++ return 0; ++} ++ ++static int zthfc_maint(struct dahdi_span *span, int cmd) { ++ return 0; ++} ++ ++static int zthfc_chanconfig(struct dahdi_chan *chan, int sigtype) { ++// printk(KERN_CRIT "chan_config sigtype=%d\n", sigtype); ++ return 0; ++} ++ ++static int zthfc_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc) { ++ span->lineconfig = lc->lineconfig; ++ return 0; ++} ++ ++static int zthfc_initialize(struct dahdi_hfc *zthfc) { ++ struct hfc_card *hfctmp = zthfc->card; ++ int i; ++ ++ memset(&zthfc->span, 0x0, sizeof(struct dahdi_span)); // you never can tell... ++ ++ 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; ++ zthfc->span.chanconfig = zthfc_chanconfig; ++ zthfc->span.startup = zthfc_startup; ++ zthfc->span.shutdown = zthfc_shutdown; ++ zthfc->span.maint = zthfc_maint; ++ zthfc->span.rbsbits = zthfc_rbsbits; ++ zthfc->span.open = zthfc_open; ++ zthfc->span.close = zthfc_close; ++ zthfc->span.ioctl = zthfc_ioctl; ++ ++ zthfc->span.channels = 3; ++ zthfc->span.chans = zthfc->_chans; ++ for (i = 0; i < zthfc->span.channels; i++) ++ zthfc->_chans[i] = &zthfc->chans[i]; ++ ++ zthfc->span.deflaw = DAHDI_LAW_ALAW; ++ zthfc->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_CCS; // <--- this is really BS ++ zthfc->span.offset = 0; ++ init_waitqueue_head(&zthfc->span.maintq); ++ zthfc->span.pvt = zthfc; ++ ++ for (i = 0; i < zthfc->span.channels; i++) { ++ memset(&(zthfc->chans[i]), 0x0, sizeof(struct dahdi_chan)); ++ sprintf(zthfc->chans[i].name, "ZTHFC%d/%d/%d", hfc_dev_count + 1,0,i + 1); ++ zthfc->chans[i].pvt = zthfc; ++ zthfc->chans[i].sigcap = DAHDI_SIG_EM | DAHDI_SIG_CLEAR | DAHDI_SIG_FXSLS | DAHDI_SIG_FXSGS | DAHDI_SIG_FXSKS | DAHDI_SIG_FXOLS | DAHDI_SIG_FXOGS | DAHDI_SIG_FXOKS | DAHDI_SIG_CAS | DAHDI_SIG_SF; ++ zthfc->chans[i].chanpos = i + 1; ++ } ++ ++ if (dahdi_register(&zthfc->span,0)) { ++ printk(KERN_CRIT "unable to register DAHDI device!\n"); ++ return -1; ++ } ++// printk(KERN_CRIT "zaphfc: registered DAHDI device!\n"); ++ 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; ++ struct dahdi_hfc *zthfc = NULL; ++ ++ tmp = pci_get_device(pcivendor, pcidevice, multi_hfc); ++ while (tmp != NULL) { ++ multi_hfc = tmp; // skip this next time. ++ ++ if (pci_enable_device(tmp)) { ++ multi_hfc = NULL; ++ return -1; ++ } ++ pci_set_master(tmp); ++ ++ hfctmp = kmalloc(sizeof(struct hfc_card), GFP_KERNEL); ++ if (!hfctmp) { ++ printk(KERN_WARNING "zaphfc: unable to kmalloc!\n"); ++ pci_disable_device(tmp); ++ multi_hfc = NULL; ++ return -ENOMEM; ++ } ++ memset(hfctmp, 0x0, sizeof(struct hfc_card)); ++ spin_lock_init(&hfctmp->lock); ++ ++ hfctmp->pcidev = tmp; ++ hfctmp->pcibus = tmp->bus->number; ++ hfctmp->pcidevfn = tmp->devfn; ++ ++ if (!tmp->irq) { ++ printk(KERN_WARNING "zaphfc: no irq!\n"); ++ } else { ++ hfctmp->irq = tmp->irq; ++ } ++ ++ hfctmp->pci_io = (char *) tmp->resource[1].start; ++ if (!hfctmp->pci_io) { ++ printk(KERN_WARNING "zaphfc: no iomem!\n"); ++ kfree(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); ++ 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); ++ 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", ++ vendor_name, card_name, ++ (unsigned long) hfctmp->pci_io, ++ (unsigned long) 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 ++ hfctmp->regs.int_m1 = 0; // no ints ++ hfctmp->regs.int_m2 = 0; // not at all ++ hfc_outb(hfctmp,hfc_INT_M1,hfctmp->regs.int_m1); ++ hfc_outb(hfctmp,hfc_INT_M2,hfctmp->regs.int_m2); ++ ++ if ((modes & (1 << hfc_dev_count)) != 0) { ++ printk(KERN_INFO "zaphfc: Card %d configured for NT mode\n",hfc_dev_count); ++ hfctmp->regs.nt_mode = 1; ++ } else { ++ printk(KERN_INFO "zaphfc: Card %d configured for TE mode\n",hfc_dev_count); ++ hfctmp->regs.nt_mode = 0; ++ } ++ ++ zthfc = kmalloc(sizeof(struct dahdi_hfc),GFP_KERNEL); ++ if (!zthfc) { ++ printk(KERN_CRIT "zaphfc: unable to kmalloc!\n"); ++ hfc_shutdownCard(hfctmp); ++ kfree(hfctmp); ++ multi_hfc = NULL; ++ return -ENOMEM; ++ } ++ memset(zthfc, 0x0, sizeof(struct dahdi_hfc)); ++ ++ zthfc->card = hfctmp; ++ zthfc_initialize(zthfc); ++ hfctmp->ztdev = zthfc; ++ ++ memset(hfctmp->drecbuf, 0x0, sizeof(hfctmp->drecbuf)); ++ hfctmp->ztdev->chans[2].readchunk = hfctmp->drecbuf; ++ ++ memset(hfctmp->dtransbuf, 0x0, sizeof(hfctmp->dtransbuf)); ++ hfctmp->ztdev->chans[2].writechunk = hfctmp->dtransbuf; ++ ++ memset(hfctmp->brecbuf[0], 0x0, sizeof(hfctmp->brecbuf[0])); ++ hfctmp->ztdev->chans[0].readchunk = hfctmp->brecbuf[0]; ++ memset(hfctmp->btransbuf[0], 0x0, sizeof(hfctmp->btransbuf[0])); ++ hfctmp->ztdev->chans[0].writechunk = hfctmp->btransbuf[0]; ++ ++ memset(hfctmp->brecbuf[1], 0x0, sizeof(hfctmp->brecbuf[1])); ++ hfctmp->ztdev->chans[1].readchunk = hfctmp->brecbuf[1]; ++ 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); ++ } ++ 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; ++ } ++ rt_set_periodic_mode(); ++#endif ++ i = 0; ++ 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); ++ while (hfc_dev_list != NULL) { ++ if (hfc_dev_list == NULL) break; ++ hfc_shutdownCard(hfc_dev_list); ++ tmpcard = hfc_dev_list; ++ hfc_dev_list = hfc_dev_list->next; ++ if (tmpcard != NULL) { ++ kfree(tmpcard); ++ tmpcard = NULL; ++ printk(KERN_INFO "zaphfc: freed one card.\n"); ++ } ++ } ++// spin_unlock(®isterlock); ++} ++#endif ++ ++ ++module_param(modes, int, 0600); ++module_param(debug, int, 0600); ++ ++MODULE_DESCRIPTION("HFC-S PCI A Zaptel Driver"); ++MODULE_AUTHOR("Klaus-Peter Junghanns <kpj@junghanns.net>"); ++#ifdef MODULE_LICENSE ++MODULE_LICENSE("GPL"); ++#endif +Index: dahdi-linux-2.1.0/drivers/dahdi/zaphfc.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ dahdi-linux-2.1.0/drivers/dahdi/zaphfc.h 2008-12-10 12:46:14.000000000 +0200 +@@ -0,0 +1,290 @@ ++/* ++ * zaphfc.h - Zaptel driver for HFC-S PCI A based ISDN BRI cards ++ * ++ * kernel module based on HFC PCI ISDN4Linux and Zaptel drivers ++ * ++ * Copyright (C) 2002, 2003, 2004, 2005 Junghanns.NET GmbH ++ * ++ * Klaus-Peter Junghanns <kpj@junghanns.net> ++ * ++ * This program is free software and may be modified and ++ * distributed under the terms of the GNU Public License. ++ * ++ */ ++ ++/* HFC register addresses - accessed using memory mapped I/O */ ++/* For a list, see datasheet section 3.2.1 at page 21 */ ++ ++#define hfc_outb(a,b,c) (writeb((c),(a)->pci_io+(b))) ++#define hfc_inb(a,b) (readb((a)->pci_io+(b))) ++ ++/* GCI/IOM bus monitor registers */ ++ ++#define hfc_C_I 0x08 ++#define hfc_TRxR 0x0C ++#define hfc_MON1_D 0x28 ++#define hfc_MON2_D 0x2C ++ ++ ++/* GCI/IOM bus timeslot registers */ ++ ++#define hfc_B1_SSL 0x80 ++#define hfc_B2_SSL 0x84 ++#define hfc_AUX1_SSL 0x88 ++#define hfc_AUX2_SSL 0x8C ++#define hfc_B1_RSL 0x90 ++#define hfc_B2_RSL 0x94 ++#define hfc_AUX1_RSL 0x98 ++#define hfc_AUX2_RSL 0x9C ++ ++/* GCI/IOM bus data registers */ ++ ++#define hfc_B1_D 0xA0 ++#define hfc_B2_D 0xA4 ++#define hfc_AUX1_D 0xA8 ++#define hfc_AUX2_D 0xAC ++ ++/* GCI/IOM bus configuration registers */ ++ ++#define hfc_MST_EMOD 0xB4 ++#define hfc_MST_MODE 0xB8 ++#define hfc_CONNECT 0xBC ++ ++ ++/* Interrupt and status registers */ ++ ++#define hfc_FIFO_EN 0x44 ++#define hfc_TRM 0x48 ++#define hfc_B_MODE 0x4C ++#define hfc_CHIP_ID 0x58 ++#define hfc_CIRM 0x60 ++#define hfc_CTMT 0x64 ++#define hfc_INT_M1 0x68 ++#define hfc_INT_M2 0x6C ++#define hfc_INT_S1 0x78 ++#define hfc_INT_S2 0x7C ++#define hfc_STATUS 0x70 ++ ++/* S/T section registers */ ++ ++#define hfc_STATES 0xC0 ++#define hfc_SCTRL 0xC4 ++#define hfc_SCTRL_E 0xC8 ++#define hfc_SCTRL_R 0xCC ++#define hfc_SQ 0xD0 ++#define hfc_CLKDEL 0xDC ++#define hfc_B1_REC 0xF0 ++#define hfc_B1_SEND 0xF0 ++#define hfc_B2_REC 0xF4 ++#define hfc_B2_SEND 0xF4 ++#define hfc_D_REC 0xF8 ++#define hfc_D_SEND 0xF8 ++#define hfc_E_REC 0xFC ++ ++/* Bits and values in various HFC PCI registers */ ++ ++/* bits in status register (READ) */ ++#define hfc_STATUS_PCI_PROC 0x02 ++#define hfc_STATUS_NBUSY 0x04 ++#define hfc_STATUS_TIMER_ELAP 0x10 ++#define hfc_STATUS_STATINT 0x20 ++#define hfc_STATUS_FRAMEINT 0x40 ++#define hfc_STATUS_ANYINT 0x80 ++ ++/* bits in CTMT (Write) */ ++#define hfc_CTMT_CLTIMER 0x80 ++#define hfc_CTMT_TIM3_125 0x04 ++#define hfc_CTMT_TIM25 0x10 ++#define hfc_CTMT_TIM50 0x14 ++#define hfc_CTMT_TIM400 0x18 ++#define hfc_CTMT_TIM800 0x1C ++#define hfc_CTMT_AUTO_TIMER 0x20 ++#define hfc_CTMT_TRANSB2 0x02 ++#define hfc_CTMT_TRANSB1 0x01 ++ ++/* bits in CIRM (Write) */ ++#define hfc_CIRM_AUX_MSK 0x07 ++#define hfc_CIRM_RESET 0x08 ++#define hfc_CIRM_B1_REV 0x40 ++#define hfc_CIRM_B2_REV 0x80 ++ ++/* bits in INT_M1 and INT_S1 */ ++#define hfc_INTS_B1TRANS 0x01 ++#define hfc_INTS_B2TRANS 0x02 ++#define hfc_INTS_DTRANS 0x04 ++#define hfc_INTS_B1REC 0x08 ++#define hfc_INTS_B2REC 0x10 ++#define hfc_INTS_DREC 0x20 ++#define hfc_INTS_L1STATE 0x40 ++#define hfc_INTS_TIMER 0x80 ++ ++/* bits in INT_M2 */ ++#define hfc_M2_PROC_TRANS 0x01 ++#define hfc_M2_GCI_I_CHG 0x02 ++#define hfc_M2_GCI_MON_REC 0x04 ++#define hfc_M2_IRQ_ENABLE 0x08 ++#define hfc_M2_PMESEL 0x80 ++ ++/* bits in STATES */ ++#define hfc_STATES_STATE_MASK 0x0F ++#define hfc_STATES_LOAD_STATE 0x10 ++#define hfc_STATES_ACTIVATE 0x20 ++#define hfc_STATES_DO_ACTION 0x40 ++#define hfc_STATES_NT_G2_G3 0x80 ++ ++/* bits in HFCD_MST_MODE */ ++#define hfc_MST_MODE_MASTER 0x01 ++#define hfc_MST_MODE_SLAVE 0x00 ++/* remaining bits are for codecs control */ ++ ++/* bits in HFCD_SCTRL */ ++#define hfc_SCTRL_B1_ENA 0x01 ++#define hfc_SCTRL_B2_ENA 0x02 ++#define hfc_SCTRL_MODE_TE 0x00 ++#define hfc_SCTRL_MODE_NT 0x04 ++#define hfc_SCTRL_LOW_PRIO 0x08 ++#define hfc_SCTRL_SQ_ENA 0x10 ++#define hfc_SCTRL_TEST 0x20 ++#define hfc_SCTRL_NONE_CAP 0x40 ++#define hfc_SCTRL_PWR_DOWN 0x80 ++ ++/* bits in SCTRL_E */ ++#define hfc_SCTRL_E_AUTO_AWAKE 0x01 ++#define hfc_SCTRL_E_DBIT_1 0x04 ++#define hfc_SCTRL_E_IGNORE_COL 0x08 ++#define hfc_SCTRL_E_CHG_B1_B2 0x80 ++ ++/* bits in FIFO_EN register */ ++#define hfc_FIFOEN_B1TX 0x01 ++#define hfc_FIFOEN_B1RX 0x02 ++#define hfc_FIFOEN_B2TX 0x04 ++#define hfc_FIFOEN_B2RX 0x08 ++#define hfc_FIFOEN_DTX 0x10 ++#define hfc_FIFOEN_DRX 0x20 ++ ++#define hfc_FIFOEN_B1 (hfc_FIFOEN_B1TX|hfc_FIFOEN_B1RX) ++#define hfc_FIFOEN_B2 (hfc_FIFOEN_B2TX|hfc_FIFOEN_B2RX) ++#define hfc_FIFOEN_D (hfc_FIFOEN_DTX|hfc_FIFOEN_DRX) ++ ++/* bits in the CONNECT register */ ++#define hfc_CONNECT_B1_shift 0 ++#define hfc_CONNECT_B2_shift 3 ++ ++#define hfc_CONNECT_HFC_from_ST 0x0 ++#define hfc_CONNECT_HFC_from_GCI 0x1 ++#define hfc_CONNECT_ST_from_HFC 0x0 ++#define hfc_CONNECT_ST_from_GCI 0x2 ++#define hfc_CONNECT_GCI_from_HFC 0x0 ++#define hfc_CONNECT_GCI_from_ST 0x4 ++ ++/* bits in the __SSL and __RSL registers */ ++#define hfc_SRSL_STIO 0x40 ++#define hfc_SRSL_ENABLE 0x80 ++#define hfc_SRCL_SLOT_MASK 0x1f ++ ++/* FIFO memory definitions */ ++ ++#define hfc_FMASK 0x000f ++#define hfc_ZMASK 0x01ff ++#define hfc_ZMASKB 0x1fff ++ ++#define hfc_D_FIFO_SIZE 0x0200 ++#define hfc_B_SUB_VAL 0x0200 ++#define hfc_B_FIFO_SIZE 0x1E00 ++#define hfc_MAX_DFRAMES 0x000f ++ ++#define hfc_FIFO_DTX_Z1 0x2080 ++#define hfc_FIFO_DTX_Z2 0x2082 ++#define hfc_FIFO_DTX_F1 0x20a0 ++#define hfc_FIFO_DTX_F2 0x20a1 ++#define hfc_FIFO_DTX 0x0000 ++#define hfc_FIFO_DTX_ZOFF 0x000 ++ ++#define hfc_FIFO_DRX_Z1 0x6080 ++#define hfc_FIFO_DRX_Z2 0x6082 ++#define hfc_FIFO_DRX_F1 0x60a0 ++#define hfc_FIFO_DRX_F2 0x60a1 ++#define hfc_FIFO_DRX 0x4000 ++#define hfc_FIFO_DRX_ZOFF 0x4000 ++ ++#define hfc_FIFO_B1TX_Z1 0x2000 ++#define hfc_FIFO_B1TX_Z2 0x2002 ++#define hfc_FIFO_B1RX_Z1 0x6000 ++#define hfc_FIFO_B1RX_Z2 0x6002 ++ ++#define hfc_FIFO_B1TX_F1 0x2080 ++#define hfc_FIFO_B1TX_F2 0x2081 ++#define hfc_FIFO_B1RX_F1 0x6080 ++#define hfc_FIFO_B1RX_F2 0x6081 ++ ++#define hfc_FIFO_B1RX_ZOFF 0x4000 ++#define hfc_FIFO_B1TX_ZOFF 0x0000 ++ ++#define hfc_FIFO_B2TX_Z1 0x2100 ++#define hfc_FIFO_B2TX_Z2 0x2102 ++#define hfc_FIFO_B2RX_Z1 0x6100 ++#define hfc_FIFO_B2RX_Z2 0x6102 ++ ++#define hfc_FIFO_B2TX_F1 0x2180 ++#define hfc_FIFO_B2TX_F2 0x2181 ++#define hfc_FIFO_B2RX_F1 0x6180 ++#define hfc_FIFO_B2RX_F2 0x6181 ++ ++#define hfc_FIFO_B2RX_ZOFF 0x6000 ++#define hfc_FIFO_B2TX_ZOFF 0x2000 ++ ++#define hfc_BTRANS_THRESHOLD 128 ++#define hfc_BTRANS_THRESMASK 0x00 ++ ++/* Structures */ ++ ++typedef struct hfc_regs { ++ unsigned char fifo_en; ++ unsigned char ctmt; ++ unsigned char int_m1; ++ unsigned char int_m2; ++ unsigned char sctrl; ++ unsigned char sctrl_e; ++ unsigned char sctrl_r; ++ unsigned char connect; ++ unsigned char trm; ++ unsigned char mst_mode; ++ unsigned char bswapped; ++ unsigned char nt_mode; ++ unsigned char int_drec; ++} hfc_regs; ++ ++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 ++ struct hfc_regs regs; ++ unsigned int pcibus; ++ unsigned int pcidevfn; ++ struct pci_dev *pcidev; ++ struct dahdi_hfc *ztdev; ++ int drecinframe; ++ unsigned char drecbuf[hfc_D_FIFO_SIZE]; ++ unsigned char dtransbuf[hfc_D_FIFO_SIZE]; ++ unsigned char brecbuf[2][DAHDI_CHUNKSIZE]; ++ unsigned char btransbuf[2][DAHDI_CHUNKSIZE]; ++ unsigned char cardno; ++ struct hfc_card *next; ++} hfc_card; ++ ++typedef struct dahdi_hfc { ++ unsigned int usecount; ++ struct dahdi_span span; ++ struct dahdi_chan chans[3]; ++ struct dahdi_chan *_chans[3]; ++ struct hfc_card *card; ++} dahdi_hfc; ++ ++/* tune this */ ++#define hfc_BCHAN_BUFFER 8 ++#define hfc_MAX_CARDS 8 diff --git a/main/dahdi-linux-hardened/linux-3.13.patch b/main/dahdi-linux-hardened/linux-3.13.patch new file mode 100644 index 0000000000..220568995f --- /dev/null +++ b/main/dahdi-linux-hardened/linux-3.13.patch @@ -0,0 +1,12 @@ +diff --git a/drivers/dahdi/zaphfc.c b/drivers/dahdi/zaphfc.c +index 0402b90..eb56f88 100644 +--- a/drivers/dahdi/zaphfc.c ++++ b/drivers/dahdi/zaphfc.c +@@ -26,6 +26,7 @@ + #include <linux/init.h> + #include <linux/interrupt.h> + #include <linux/delay.h> ++#include <linux/sched.h> + #include <dahdi/kernel.h> + #include "zaphfc.h" + diff --git a/main/dahdi-linux-hardened/linux-4.4.patch b/main/dahdi-linux-hardened/linux-4.4.patch new file mode 100644 index 0000000000..fe6105319d --- /dev/null +++ b/main/dahdi-linux-hardened/linux-4.4.patch @@ -0,0 +1,10 @@ +--- ./drivers/dahdi/zaphfc.c.orig ++++ ./drivers/dahdi/zaphfc.c +@@ -27,6 +27,7 @@ + #include <linux/interrupt.h> + #include <linux/delay.h> + #include <linux/sched.h> ++#include <linux/vmalloc.h> + #include <dahdi/kernel.h> + #include "zaphfc.h" + diff --git a/main/dahdi-linux-hardened/zaphfc-dahdi-2.4.0.patch b/main/dahdi-linux-hardened/zaphfc-dahdi-2.4.0.patch new file mode 100644 index 0000000000..80500a574a --- /dev/null +++ b/main/dahdi-linux-hardened/zaphfc-dahdi-2.4.0.patch @@ -0,0 +1,58 @@ +Index: dahdi-linux-2.4.0/drivers/dahdi/zaphfc.c +=================================================================== +--- dahdi-linux-2.4.0.orig/drivers/dahdi/zaphfc.c 2010-10-26 14:41:21.000000000 +0300 ++++ dahdi-linux-2.4.0/drivers/dahdi/zaphfc.c 2010-10-26 14:50:14.000000000 +0300 +@@ -617,7 +617,7 @@ + } + + static int zthfc_startup(struct dahdi_span *span) { +- struct dahdi_hfc *zthfc = span->pvt; ++ struct dahdi_hfc *zthfc = container_of(span, struct dahdi_hfc, span); + struct hfc_card *hfctmp = zthfc->card; + int alreadyrunning; + +@@ -663,6 +663,19 @@ + return 0; + } + ++static const struct dahdi_span_ops zaphfc_span_ops = { ++ .owner = THIS_MODULE, ++ .spanconfig = zthfc_spanconfig, ++ .chanconfig = zthfc_chanconfig, ++ .startup = zthfc_startup, ++ .shutdown = zthfc_shutdown, ++ .maint = zthfc_maint, ++ .rbsbits = zthfc_rbsbits, ++ .open = zthfc_open, ++ .close = zthfc_close, ++ .ioctl = zthfc_ioctl, ++}; ++ + static int zthfc_initialize(struct dahdi_hfc *zthfc) { + struct hfc_card *hfctmp = zthfc->card; + int i; +@@ -676,15 +689,7 @@ + sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE]", hfc_dev_count + 1); + } + +- zthfc->span.spanconfig = zthfc_spanconfig; +- zthfc->span.chanconfig = zthfc_chanconfig; +- zthfc->span.startup = zthfc_startup; +- zthfc->span.shutdown = zthfc_shutdown; +- zthfc->span.maint = zthfc_maint; +- zthfc->span.rbsbits = zthfc_rbsbits; +- zthfc->span.open = zthfc_open; +- zthfc->span.close = zthfc_close; +- zthfc->span.ioctl = zthfc_ioctl; ++ zthfc->span.ops = &zaphfc_span_ops; + + zthfc->span.channels = 3; + zthfc->span.chans = zthfc->_chans; +@@ -695,7 +700,6 @@ + zthfc->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_CCS; // <--- this is really BS + zthfc->span.offset = 0; + init_waitqueue_head(&zthfc->span.maintq); +- zthfc->span.pvt = zthfc; + + for (i = 0; i < zthfc->span.channels; i++) { + memset(&(zthfc->chans[i]), 0x0, sizeof(struct dahdi_chan)); diff --git a/main/dahdi-linux-hardened/zaphfc-dahdi-2.5.0.patch b/main/dahdi-linux-hardened/zaphfc-dahdi-2.5.0.patch new file mode 100644 index 0000000000..37a1e76ba8 --- /dev/null +++ b/main/dahdi-linux-hardened/zaphfc-dahdi-2.5.0.patch @@ -0,0 +1,36 @@ +Index: dahdi-linux-2.5.0/drivers/dahdi/zaphfc.c +=================================================================== +--- dahdi-linux-2.5.0.orig/drivers/dahdi/zaphfc.c 2011-08-15 14:29:51.000000000 +0300 ++++ dahdi-linux-2.5.0/drivers/dahdi/zaphfc.c 2011-08-15 14:30:11.000000000 +0300 +@@ -616,7 +616,7 @@ + return 0; + } + +-static int zthfc_startup(struct dahdi_span *span) { ++static int zthfc_startup(struct file *file, struct dahdi_span *span) { + struct dahdi_hfc *zthfc = container_of(span, struct dahdi_hfc, span); + struct hfc_card *hfctmp = zthfc->card; + int alreadyrunning; +@@ -653,12 +653,12 @@ + return 0; + } + +-static int zthfc_chanconfig(struct dahdi_chan *chan, int sigtype) { ++static int zthfc_chanconfig(struct file *file, struct dahdi_chan *chan, int sigtype) { + // printk(KERN_CRIT "chan_config sigtype=%d\n", sigtype); + return 0; + } + +-static int zthfc_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc) { ++static int zthfc_spanconfig(struct file *file, struct dahdi_span *span, struct dahdi_lineconfig *lc) { + span->lineconfig = lc->lineconfig; + return 0; + } +@@ -699,7 +699,6 @@ + zthfc->span.deflaw = DAHDI_LAW_ALAW; + zthfc->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_CCS; // <--- this is really BS + zthfc->span.offset = 0; +- init_waitqueue_head(&zthfc->span.maintq); + + for (i = 0; i < zthfc->span.channels; i++) { + memset(&(zthfc->chans[i]), 0x0, sizeof(struct dahdi_chan)); diff --git a/main/dahdi-linux-hardened/zaphfc-dahdi-2.6.0.patch b/main/dahdi-linux-hardened/zaphfc-dahdi-2.6.0.patch new file mode 100644 index 0000000000..5a77438462 --- /dev/null +++ b/main/dahdi-linux-hardened/zaphfc-dahdi-2.6.0.patch @@ -0,0 +1,58 @@ +--- dahdi-linux-2.6.0/drivers/dahdi/zaphfc.c.orig 2012-01-25 14:08:58.000000000 +0200 ++++ dahdi-linux-2.6.0/drivers/dahdi/zaphfc.c 2012-01-25 14:29:26.000000000 +0200 +@@ -122,7 +122,10 @@ + } + spin_unlock_irqrestore(&hfctmp->lock,flags); + if (hfctmp->ztdev != NULL) { +- dahdi_unregister(&hfctmp->ztdev->span); ++ if (hfctmp->ztdev->ddev) { ++ dahdi_unregister_device(hfctmp->ztdev->ddev); ++ dahdi_free_device(hfctmp->ztdev->ddev); ++ } + vfree(hfctmp->ztdev); + printk(KERN_INFO "unregistered from DAHDI.\n"); + } +@@ -680,9 +683,15 @@ + struct hfc_card *hfctmp = zthfc->card; + int i; + ++ zthfc->ddev = dahdi_create_device(); ++ if (!zthfc->ddev) ++ return -ENOMEM; ++ ++ zthfc->ddev->manufacturer = "HFC"; ++ + memset(&zthfc->span, 0x0, sizeof(struct dahdi_span)); // you never can tell... + +- sprintf(zthfc->span.name, "ZTHFC%d", hfc_dev_count + 1); ++ sprintf(zthfc->span.name, "ZTHFC/%d", hfc_dev_count + 1); + if (hfctmp->regs.nt_mode == 1) { + sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT]", hfc_dev_count + 1); + } else { +@@ -702,13 +711,14 @@ + + for (i = 0; i < zthfc->span.channels; i++) { + memset(&(zthfc->chans[i]), 0x0, sizeof(struct dahdi_chan)); +- sprintf(zthfc->chans[i].name, "ZTHFC%d/%d/%d", hfc_dev_count + 1,0,i + 1); ++ sprintf(zthfc->chans[i].name, "ZTHFC/%d/%d/%d", hfc_dev_count + 1,0,i + 1); + zthfc->chans[i].pvt = zthfc; + zthfc->chans[i].sigcap = DAHDI_SIG_EM | DAHDI_SIG_CLEAR | DAHDI_SIG_FXSLS | DAHDI_SIG_FXSGS | DAHDI_SIG_FXSKS | DAHDI_SIG_FXOLS | DAHDI_SIG_FXOGS | DAHDI_SIG_FXOKS | DAHDI_SIG_CAS | DAHDI_SIG_SF; + zthfc->chans[i].chanpos = i + 1; + } + +- if (dahdi_register(&zthfc->span,0)) { ++ list_add_tail(&zthfc->span.device_node, &zthfc->ddev->spans); ++ if (dahdi_register_device(zthfc->ddev, &zthfc->card->pcidev->dev)) { + printk(KERN_CRIT "unable to register DAHDI device!\n"); + return -1; + } +--- dahdi-linux-2.6.0/drivers/dahdi/zaphfc.h.orig 2012-01-25 14:23:37.000000000 +0200 ++++ dahdi-linux-2.6.0/drivers/dahdi/zaphfc.h 2012-01-25 14:24:33.000000000 +0200 +@@ -339,6 +339,7 @@ + struct dahdi_span span; + struct dahdi_chan chans[3]; + struct dahdi_chan *_chans[3]; ++ struct dahdi_device *ddev; + struct hfc_card *card; + } dahdi_hfc; + diff --git a/main/dahdi-linux-hardened/zaphfc-dahdi-2.7.0.patch b/main/dahdi-linux-hardened/zaphfc-dahdi-2.7.0.patch new file mode 100644 index 0000000000..624cfe7b9a --- /dev/null +++ b/main/dahdi-linux-hardened/zaphfc-dahdi-2.7.0.patch @@ -0,0 +1,32 @@ +--- dahdi-linux-2.7.0/drivers/dahdi/zaphfc.c.orig 2013-11-13 14:47:31.772140792 +0200 ++++ dahdi-linux-2.7.0/drivers/dahdi/zaphfc.c 2013-11-13 14:55:20.136270113 +0200 +@@ -687,19 +687,18 @@ + if (!zthfc->ddev) + return -ENOMEM; + +- zthfc->ddev->manufacturer = "HFC"; +- ++ zthfc->ddev->manufacturer = "Cologne Chips"; ++ zthfc->ddev->devicetype = "HFC-S PCI-A ISDN"; ++ zthfc->ddev->location = kasprintf(GFP_KERNEL, ++ "PCI Bus %02d Slot %02d", ++ hfctmp->pcidev->bus->number, ++ PCI_SLOT(hfctmp->pcidev->devfn) + 1); + memset(&zthfc->span, 0x0, sizeof(struct dahdi_span)); // you never can tell... +- + sprintf(zthfc->span.name, "ZTHFC/%d", hfc_dev_count + 1); +- if (hfctmp->regs.nt_mode == 1) { +- sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [NT]", hfc_dev_count + 1); +- } else { +- sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [TE]", hfc_dev_count + 1); +- } +- ++ sprintf(zthfc->span.desc, "HFC-S PCI A ISDN card %d [%s]", ++ hfc_dev_count + 1, hfctmp->regs.nt_mode ? "NT" : "TE"); ++ zthfc->span.spantype = hfctmp->regs.nt_mode ? SPANTYPE_DIGITAL_BRI_NT : SPANTYPE_DIGITAL_BRI_TE; + zthfc->span.ops = &zaphfc_span_ops; +- + zthfc->span.channels = 3; + zthfc->span.chans = zthfc->_chans; + for (i = 0; i < zthfc->span.channels; i++) + diff --git a/main/dahdi-linux-hardened/zaphfc-dahdi-flortz.diff b/main/dahdi-linux-hardened/zaphfc-dahdi-flortz.diff new file mode 100644 index 0000000000..dc856c97c7 --- /dev/null +++ b/main/dahdi-linux-hardened/zaphfc-dahdi-flortz.diff @@ -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 <kpj@junghanns.net> + * ++ * Copyright (C) 2004, 2005, 2006 Florian Zumbiehl <florz@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> +@@ -29,6 +31,8 @@ + + #include <linux/moduleparam.h> + ++#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; 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 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<<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 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 <kpj@junghanns.net>"); |